aws-cdk 2.1143.0 → 2.1144.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/THIRD_PARTY_LICENSES +22 -22
- package/build-info.json +2 -2
- package/db.json.gz +0 -0
- package/lib/api-private-error.d.ts +1 -0
- package/lib/api-private-error.js +9 -0
- package/lib/cli/cli.js +6 -5
- package/lib/cli/io-host/cli-io-host.d.ts +21 -2
- package/lib/cli/io-host/cli-io-host.js +9 -8
- package/lib/cli/proxy-agent.d.ts +55 -4
- package/lib/cli/proxy-agent.js +71 -33
- package/lib/cli/telemetry/post-telemetry.d.ts +31 -0
- package/lib/cli/telemetry/post-telemetry.js +76 -0
- package/lib/cli/telemetry/sender-bundle.d.ts +1 -0
- package/lib/cli/telemetry/sender-bundle.js +32542 -0
- package/lib/cli/telemetry/sender.d.ts +50 -0
- package/lib/cli/telemetry/sender.js +103 -0
- package/lib/cli/telemetry/sink/subprocess-sink.d.ts +77 -0
- package/lib/cli/telemetry/sink/subprocess-sink.js +209 -0
- package/lib/index.js +2801 -2364
- package/lib/index_bg.wasm +0 -0
- package/lib/init-templates/.init-version.json +1 -1
- package/package.json +9 -9
- package/lib/cli/telemetry/sink/endpoint-sink.d.ts +0 -44
- package/lib/cli/telemetry/sink/endpoint-sink.js +0 -108
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { TelemetryBatch } from './post-telemetry';
|
|
2
|
+
import type { ProxyAgentDiagnostics } from '../proxy-agent';
|
|
3
|
+
/**
|
|
4
|
+
* What the parent hands to this process.
|
|
5
|
+
*/
|
|
6
|
+
export interface TelemetrySenderConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Absolute URL to POST the telemetry payload to.
|
|
9
|
+
*/
|
|
10
|
+
readonly endpoint: string;
|
|
11
|
+
/**
|
|
12
|
+
* The batch of events to deliver.
|
|
13
|
+
*/
|
|
14
|
+
readonly body: TelemetryBatch;
|
|
15
|
+
/**
|
|
16
|
+
* Proxy to route through. An empty string means "explicitly no proxy", as `--proxy ''` does.
|
|
17
|
+
*
|
|
18
|
+
* @default - resolved from the inherited proxy environment variables, as in the parent
|
|
19
|
+
*/
|
|
20
|
+
readonly proxyUrl?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Absolute path to a CA bundle to trust. The path, not the contents: a system bundle is ~190KB.
|
|
23
|
+
*
|
|
24
|
+
* @default - the default Node trust store, plus anything in `NODE_EXTRA_CA_CERTS`
|
|
25
|
+
*/
|
|
26
|
+
readonly caBundlePath?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Budget for the delivery attempt, in milliseconds.
|
|
29
|
+
*
|
|
30
|
+
* @default 10000
|
|
31
|
+
*/
|
|
32
|
+
readonly timeoutMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* POST a telemetry payload, routing through a proxy when one applies.
|
|
36
|
+
*
|
|
37
|
+
* Returns the status code for the caller to judge, and lets failures reject: every outcome is handled
|
|
38
|
+
* in one place, in the entry point.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sendTelemetry(cfg: TelemetrySenderConfig): Promise<number | undefined>;
|
|
41
|
+
export declare function isSuccess(statusCode: number | undefined): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Diagnostics for the detached child, which has no IoHost.
|
|
44
|
+
*/
|
|
45
|
+
export declare const senderDiagnostics: ProxyAgentDiagnostics;
|
|
46
|
+
/**
|
|
47
|
+
* Only visible when the parent was run with `CDK_TELEMETRY_SENDER_DEBUG=1`, which is also what makes
|
|
48
|
+
* it pass this process's stderr through. Synchronous because `process.exit` discards buffered writes.
|
|
49
|
+
*/
|
|
50
|
+
export declare function trace(message: string): void;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.senderDiagnostics = void 0;
|
|
37
|
+
exports.sendTelemetry = sendTelemetry;
|
|
38
|
+
exports.isSuccess = isSuccess;
|
|
39
|
+
exports.trace = trace;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const post_telemetry_1 = require("./post-telemetry");
|
|
42
|
+
const api_private_error_1 = require("../../api-private-error");
|
|
43
|
+
const proxy_agent_1 = require("../proxy-agent");
|
|
44
|
+
/**
|
|
45
|
+
* Budget for the delivery attempt.
|
|
46
|
+
*
|
|
47
|
+
* Generous because nothing is waiting on it: this process is detached and the CLI has already exited,
|
|
48
|
+
* so the only thing a longer timeout costs is a background process living a little longer. It has to
|
|
49
|
+
* cover a proxy handshake plus the POST on a loaded machine.
|
|
50
|
+
*/
|
|
51
|
+
const NETWORK_TIMEOUT_MS = 10_000;
|
|
52
|
+
/**
|
|
53
|
+
* POST a telemetry payload, routing through a proxy when one applies.
|
|
54
|
+
*
|
|
55
|
+
* Returns the status code for the caller to judge, and lets failures reject: every outcome is handled
|
|
56
|
+
* in one place, in the entry point.
|
|
57
|
+
*/
|
|
58
|
+
async function sendTelemetry(cfg) {
|
|
59
|
+
if (!cfg?.endpoint) {
|
|
60
|
+
throw new api_private_error_1.ToolkitError('NoEndpoint', 'No telemetry endpoint was given');
|
|
61
|
+
}
|
|
62
|
+
const url = new URL(cfg.endpoint);
|
|
63
|
+
// The provider the CLI itself uses, so the child routes the way the parent would have, including
|
|
64
|
+
// SOCKS and PAC proxies and NO_PROXY from the inherited environment.
|
|
65
|
+
const { agent } = await new proxy_agent_1.ProxyAgentProvider(exports.senderDiagnostics).create({
|
|
66
|
+
proxyAddress: cfg.proxyUrl,
|
|
67
|
+
caBundlePath: cfg.caBundlePath,
|
|
68
|
+
});
|
|
69
|
+
const res = await (0, post_telemetry_1.postTelemetry)(url, cfg.body ?? { events: [] }, {
|
|
70
|
+
agent,
|
|
71
|
+
timeoutMs: cfg.timeoutMs ?? NETWORK_TIMEOUT_MS,
|
|
72
|
+
});
|
|
73
|
+
// Drain, or the socket is never released.
|
|
74
|
+
res.resume();
|
|
75
|
+
return res.statusCode;
|
|
76
|
+
}
|
|
77
|
+
function isSuccess(statusCode) {
|
|
78
|
+
return statusCode !== undefined && statusCode >= 200 && statusCode < 300;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Diagnostics for the detached child, which has no IoHost.
|
|
82
|
+
*/
|
|
83
|
+
exports.senderDiagnostics = {
|
|
84
|
+
defaults: {
|
|
85
|
+
debug: async (message) => trace(message),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Only visible when the parent was run with `CDK_TELEMETRY_SENDER_DEBUG=1`, which is also what makes
|
|
90
|
+
* it pass this process's stderr through. Synchronous because `process.exit` discards buffered writes.
|
|
91
|
+
*/
|
|
92
|
+
function trace(message) {
|
|
93
|
+
if (process.env.CDK_TELEMETRY_SENDER_DEBUG !== '1') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
fs.writeSync(2, `[cdk-telemetry-sender] ${message}\n`);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Diagnostics must never be the reason anything fails.
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2VuZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBEQSxzQ0F1QkM7QUFFRCw4QkFFQztBQWVELHNCQVNDO0FBN0dELDRDQUE4QjtBQUU5QixxREFBaUQ7QUFDakQsK0RBQXVEO0FBRXZELGdEQUFvRDtBQUVwRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQztBQXNDbEM7Ozs7O0dBS0c7QUFDSSxLQUFLLFVBQVUsYUFBYSxDQUFDLEdBQTBCO0lBQzVELElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDbkIsTUFBTSxJQUFJLGdDQUFZLENBQUMsWUFBWSxFQUFFLGlDQUFpQyxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUVELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUVsQyxpR0FBaUc7SUFDakcscUVBQXFFO0lBQ3JFLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLElBQUksZ0NBQWtCLENBQUMseUJBQWlCLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDdkUsWUFBWSxFQUFFLEdBQUcsQ0FBQyxRQUFRO1FBQzFCLFlBQVksRUFBRSxHQUFHLENBQUMsWUFBWTtLQUMvQixDQUFDLENBQUM7SUFFSCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUEsOEJBQWEsRUFBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRTtRQUMvRCxLQUFLO1FBQ0wsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTLElBQUksa0JBQWtCO0tBQy9DLENBQUMsQ0FBQztJQUVILDBDQUEwQztJQUMxQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7SUFFYixPQUFPLEdBQUcsQ0FBQyxVQUFVLENBQUM7QUFDeEIsQ0FBQztBQUVELFNBQWdCLFNBQVMsQ0FBQyxVQUE4QjtJQUN0RCxPQUFPLFVBQVUsS0FBSyxTQUFTLElBQUksVUFBVSxJQUFJLEdBQUcsSUFBSSxVQUFVLEdBQUcsR0FBRyxDQUFDO0FBQzNFLENBQUM7QUFFRDs7R0FFRztBQUNVLFFBQUEsaUJBQWlCLEdBQTBCO0lBQ3RELFFBQVEsRUFBRTtRQUNSLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBZSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDO0tBQ2pEO0NBQ0YsQ0FBQztBQUVGOzs7R0FHRztBQUNILFNBQWdCLEtBQUssQ0FBQyxPQUFlO0lBQ25DLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNuRCxPQUFPO0lBQ1QsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLDBCQUEwQixPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCx1REFBdUQ7SUFDekQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdub2RlOmZzJztcbmltcG9ydCB0eXBlIHsgVGVsZW1ldHJ5QmF0Y2ggfSBmcm9tICcuL3Bvc3QtdGVsZW1ldHJ5JztcbmltcG9ydCB7IHBvc3RUZWxlbWV0cnkgfSBmcm9tICcuL3Bvc3QtdGVsZW1ldHJ5JztcbmltcG9ydCB7IFRvb2xraXRFcnJvciB9IGZyb20gJy4uLy4uL2FwaS1wcml2YXRlLWVycm9yJztcbmltcG9ydCB0eXBlIHsgUHJveHlBZ2VudERpYWdub3N0aWNzIH0gZnJvbSAnLi4vcHJveHktYWdlbnQnO1xuaW1wb3J0IHsgUHJveHlBZ2VudFByb3ZpZGVyIH0gZnJvbSAnLi4vcHJveHktYWdlbnQnO1xuXG4vKipcbiAqIEJ1ZGdldCBmb3IgdGhlIGRlbGl2ZXJ5IGF0dGVtcHQuXG4gKlxuICogR2VuZXJvdXMgYmVjYXVzZSBub3RoaW5nIGlzIHdhaXRpbmcgb24gaXQ6IHRoaXMgcHJvY2VzcyBpcyBkZXRhY2hlZCBhbmQgdGhlIENMSSBoYXMgYWxyZWFkeSBleGl0ZWQsXG4gKiBzbyB0aGUgb25seSB0aGluZyBhIGxvbmdlciB0aW1lb3V0IGNvc3RzIGlzIGEgYmFja2dyb3VuZCBwcm9jZXNzIGxpdmluZyBhIGxpdHRsZSBsb25nZXIuIEl0IGhhcyB0b1xuICogY292ZXIgYSBwcm94eSBoYW5kc2hha2UgcGx1cyB0aGUgUE9TVCBvbiBhIGxvYWRlZCBtYWNoaW5lLlxuICovXG5jb25zdCBORVRXT1JLX1RJTUVPVVRfTVMgPSAxMF8wMDA7XG5cbi8qKlxuICogV2hhdCB0aGUgcGFyZW50IGhhbmRzIHRvIHRoaXMgcHJvY2Vzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZWxlbWV0cnlTZW5kZXJDb25maWcge1xuICAvKipcbiAgICogQWJzb2x1dGUgVVJMIHRvIFBPU1QgdGhlIHRlbGVtZXRyeSBwYXlsb2FkIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgZW5kcG9pbnQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGJhdGNoIG9mIGV2ZW50cyB0byBkZWxpdmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgYm9keTogVGVsZW1ldHJ5QmF0Y2g7XG5cbiAgLyoqXG4gICAqIFByb3h5IHRvIHJvdXRlIHRocm91Z2guIEFuIGVtcHR5IHN0cmluZyBtZWFucyBcImV4cGxpY2l0bHkgbm8gcHJveHlcIiwgYXMgYC0tcHJveHkgJydgIGRvZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcmVzb2x2ZWQgZnJvbSB0aGUgaW5oZXJpdGVkIHByb3h5IGVudmlyb25tZW50IHZhcmlhYmxlcywgYXMgaW4gdGhlIHBhcmVudFxuICAgKi9cbiAgcmVhZG9ubHkgcHJveHlVcmw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gYSBDQSBidW5kbGUgdG8gdHJ1c3QuIFRoZSBwYXRoLCBub3QgdGhlIGNvbnRlbnRzOiBhIHN5c3RlbSBidW5kbGUgaXMgfjE5MEtCLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBkZWZhdWx0IE5vZGUgdHJ1c3Qgc3RvcmUsIHBsdXMgYW55dGhpbmcgaW4gYE5PREVfRVhUUkFfQ0FfQ0VSVFNgXG4gICAqL1xuICByZWFkb25seSBjYUJ1bmRsZVBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEJ1ZGdldCBmb3IgdGhlIGRlbGl2ZXJ5IGF0dGVtcHQsIGluIG1pbGxpc2Vjb25kcy5cbiAgICpcbiAgICogQGRlZmF1bHQgMTAwMDBcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXRNcz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBQT1NUIGEgdGVsZW1ldHJ5IHBheWxvYWQsIHJvdXRpbmcgdGhyb3VnaCBhIHByb3h5IHdoZW4gb25lIGFwcGxpZXMuXG4gKlxuICogUmV0dXJucyB0aGUgc3RhdHVzIGNvZGUgZm9yIHRoZSBjYWxsZXIgdG8ganVkZ2UsIGFuZCBsZXRzIGZhaWx1cmVzIHJlamVjdDogZXZlcnkgb3V0Y29tZSBpcyBoYW5kbGVkXG4gKiBpbiBvbmUgcGxhY2UsIGluIHRoZSBlbnRyeSBwb2ludC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmRUZWxlbWV0cnkoY2ZnOiBUZWxlbWV0cnlTZW5kZXJDb25maWcpOiBQcm9taXNlPG51bWJlciB8IHVuZGVmaW5lZD4ge1xuICBpZiAoIWNmZz8uZW5kcG9pbnQpIHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdOb0VuZHBvaW50JywgJ05vIHRlbGVtZXRyeSBlbmRwb2ludCB3YXMgZ2l2ZW4nKTtcbiAgfVxuXG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoY2ZnLmVuZHBvaW50KTtcblxuICAvLyBUaGUgcHJvdmlkZXIgdGhlIENMSSBpdHNlbGYgdXNlcywgc28gdGhlIGNoaWxkIHJvdXRlcyB0aGUgd2F5IHRoZSBwYXJlbnQgd291bGQgaGF2ZSwgaW5jbHVkaW5nXG4gIC8vIFNPQ0tTIGFuZCBQQUMgcHJveGllcyBhbmQgTk9fUFJPWFkgZnJvbSB0aGUgaW5oZXJpdGVkIGVudmlyb25tZW50LlxuICBjb25zdCB7IGFnZW50IH0gPSBhd2FpdCBuZXcgUHJveHlBZ2VudFByb3ZpZGVyKHNlbmRlckRpYWdub3N0aWNzKS5jcmVhdGUoe1xuICAgIHByb3h5QWRkcmVzczogY2ZnLnByb3h5VXJsLFxuICAgIGNhQnVuZGxlUGF0aDogY2ZnLmNhQnVuZGxlUGF0aCxcbiAgfSk7XG5cbiAgY29uc3QgcmVzID0gYXdhaXQgcG9zdFRlbGVtZXRyeSh1cmwsIGNmZy5ib2R5ID8/IHsgZXZlbnRzOiBbXSB9LCB7XG4gICAgYWdlbnQsXG4gICAgdGltZW91dE1zOiBjZmcudGltZW91dE1zID8/IE5FVFdPUktfVElNRU9VVF9NUyxcbiAgfSk7XG5cbiAgLy8gRHJhaW4sIG9yIHRoZSBzb2NrZXQgaXMgbmV2ZXIgcmVsZWFzZWQuXG4gIHJlcy5yZXN1bWUoKTtcblxuICByZXR1cm4gcmVzLnN0YXR1c0NvZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1N1Y2Nlc3Moc3RhdHVzQ29kZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIHJldHVybiBzdGF0dXNDb2RlICE9PSB1bmRlZmluZWQgJiYgc3RhdHVzQ29kZSA+PSAyMDAgJiYgc3RhdHVzQ29kZSA8IDMwMDtcbn1cblxuLyoqXG4gKiBEaWFnbm9zdGljcyBmb3IgdGhlIGRldGFjaGVkIGNoaWxkLCB3aGljaCBoYXMgbm8gSW9Ib3N0LlxuICovXG5leHBvcnQgY29uc3Qgc2VuZGVyRGlhZ25vc3RpY3M6IFByb3h5QWdlbnREaWFnbm9zdGljcyA9IHtcbiAgZGVmYXVsdHM6IHtcbiAgICBkZWJ1ZzogYXN5bmMgKG1lc3NhZ2U6IHN0cmluZykgPT4gdHJhY2UobWVzc2FnZSksXG4gIH0sXG59O1xuXG4vKipcbiAqIE9ubHkgdmlzaWJsZSB3aGVuIHRoZSBwYXJlbnQgd2FzIHJ1biB3aXRoIGBDREtfVEVMRU1FVFJZX1NFTkRFUl9ERUJVRz0xYCwgd2hpY2ggaXMgYWxzbyB3aGF0IG1ha2VzXG4gKiBpdCBwYXNzIHRoaXMgcHJvY2VzcydzIHN0ZGVyciB0aHJvdWdoLiBTeW5jaHJvbm91cyBiZWNhdXNlIGBwcm9jZXNzLmV4aXRgIGRpc2NhcmRzIGJ1ZmZlcmVkIHdyaXRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYWNlKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICBpZiAocHJvY2Vzcy5lbnYuQ0RLX1RFTEVNRVRSWV9TRU5ERVJfREVCVUcgIT09ICcxJykge1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGZzLndyaXRlU3luYygyLCBgW2Nkay10ZWxlbWV0cnktc2VuZGVyXSAke21lc3NhZ2V9XFxuYCk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIERpYWdub3N0aWNzIG11c3QgbmV2ZXIgYmUgdGhlIHJlYXNvbiBhbnl0aGluZyBmYWlscy5cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { IIoHost } from '../../io-host';
|
|
2
|
+
import type { TelemetrySchema } from '../schema';
|
|
3
|
+
import type { ITelemetrySink } from './sink-interface';
|
|
4
|
+
/**
|
|
5
|
+
* Reports a successful hand-off, NOT a successful delivery.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DISPATCHED_TRACE = "Telemetry dispatched";
|
|
8
|
+
/**
|
|
9
|
+
* Properties for the subprocess telemetry sink.
|
|
10
|
+
*/
|
|
11
|
+
export interface SubprocessTelemetrySinkProps {
|
|
12
|
+
/**
|
|
13
|
+
* The external endpoint to hit
|
|
14
|
+
*/
|
|
15
|
+
readonly endpoint: string;
|
|
16
|
+
/**
|
|
17
|
+
* Where messages are going to be sent
|
|
18
|
+
*/
|
|
19
|
+
readonly ioHost: IIoHost;
|
|
20
|
+
/**
|
|
21
|
+
* Proxy the sender should route through, as configured by `--proxy` or the `proxy` setting.
|
|
22
|
+
*
|
|
23
|
+
* @default - resolved from the environment by the sender, as `proxy-agent` does for the rest of the CLI
|
|
24
|
+
*/
|
|
25
|
+
readonly proxyUrl?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Absolute path to the CA bundle to trust, as configured by `--ca-bundle-path` or `AWS_CA_BUNDLE`.
|
|
28
|
+
*
|
|
29
|
+
* @default - only the system trust store
|
|
30
|
+
*/
|
|
31
|
+
readonly caBundlePath?: string;
|
|
32
|
+
/**
|
|
33
|
+
* How to locate the bundled sender entry point.
|
|
34
|
+
*
|
|
35
|
+
* Injectable so a test can exercise the missing-sender path without reaching into this object's
|
|
36
|
+
* privates; returning undefined is what "not on disk" looks like.
|
|
37
|
+
*
|
|
38
|
+
* @default - looked up relative to this package's root
|
|
39
|
+
*/
|
|
40
|
+
readonly resolveSender?: () => string | undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A telemetry sink that delivers events from a detached child process.
|
|
44
|
+
*
|
|
45
|
+
* Events are written to a temporary file and handed to a child that outlives us, so the CLI can exit
|
|
46
|
+
* immediately instead of waiting on the network. Nothing here ever learns whether delivery succeeded.
|
|
47
|
+
*
|
|
48
|
+
* Deliberately does not check connectivity first: that check would itself be a network call on the
|
|
49
|
+
* exit path, which is what this sink exists to avoid.
|
|
50
|
+
*/
|
|
51
|
+
export declare class SubprocessTelemetrySink implements ITelemetrySink {
|
|
52
|
+
private events;
|
|
53
|
+
private endpoint;
|
|
54
|
+
private ioHelper;
|
|
55
|
+
private senderPath?;
|
|
56
|
+
private proxyUrl?;
|
|
57
|
+
private caBundlePath?;
|
|
58
|
+
constructor(props: SubprocessTelemetrySinkProps);
|
|
59
|
+
/**
|
|
60
|
+
* Add an event to the collection.
|
|
61
|
+
*/
|
|
62
|
+
emit(event: TelemetrySchema): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Hand whatever has accumulated to a detached sender.
|
|
65
|
+
*
|
|
66
|
+
* Clears the batch either way: delivery is one-shot, the process that would retry has usually
|
|
67
|
+
* exited, and retaining the events would just re-report the failure and regrow the batch every 30s.
|
|
68
|
+
* This is the single place delivery failures are handled; `dispatch` reports them by throwing.
|
|
69
|
+
*/
|
|
70
|
+
flush(): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Hand the batch to a detached sender process.
|
|
73
|
+
*
|
|
74
|
+
* Throws if the batch could not be handed over.
|
|
75
|
+
*/
|
|
76
|
+
private dispatch;
|
|
77
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SubprocessTelemetrySink = exports.DISPATCHED_TRACE = void 0;
|
|
37
|
+
// eslint-disable-next-line no-restricted-imports -- the detached sender must outlive the CLI; run/runSync from the subprocess tool monitor the child to completion
|
|
38
|
+
const node_child_process_1 = require("node:child_process");
|
|
39
|
+
const node_crypto_1 = require("node:crypto");
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const os = __importStar(require("node:os"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const api_private_1 = require("../../../api-private");
|
|
44
|
+
const api_private_error_1 = require("../../../api-private-error");
|
|
45
|
+
const root_dir_1 = require("../../root-dir");
|
|
46
|
+
/**
|
|
47
|
+
* The bundled sender entry point, relative to this package's root.
|
|
48
|
+
*/
|
|
49
|
+
const SENDER_ENTRY_POINT = path.join('lib', 'cli', 'telemetry', 'sender-bundle.js');
|
|
50
|
+
/**
|
|
51
|
+
* Reports a successful hand-off, NOT a successful delivery.
|
|
52
|
+
*/
|
|
53
|
+
exports.DISPATCHED_TRACE = 'Telemetry dispatched';
|
|
54
|
+
/**
|
|
55
|
+
* A telemetry sink that delivers events from a detached child process.
|
|
56
|
+
*
|
|
57
|
+
* Events are written to a temporary file and handed to a child that outlives us, so the CLI can exit
|
|
58
|
+
* immediately instead of waiting on the network. Nothing here ever learns whether delivery succeeded.
|
|
59
|
+
*
|
|
60
|
+
* Deliberately does not check connectivity first: that check would itself be a network call on the
|
|
61
|
+
* exit path, which is what this sink exists to avoid.
|
|
62
|
+
*/
|
|
63
|
+
class SubprocessTelemetrySink {
|
|
64
|
+
events = [];
|
|
65
|
+
endpoint;
|
|
66
|
+
ioHelper;
|
|
67
|
+
senderPath;
|
|
68
|
+
proxyUrl;
|
|
69
|
+
caBundlePath;
|
|
70
|
+
constructor(props) {
|
|
71
|
+
this.endpoint = new URL(props.endpoint);
|
|
72
|
+
if (!this.endpoint.hostname || !this.endpoint.pathname) {
|
|
73
|
+
throw new api_private_error_1.ToolkitError('MalformedEndpoint', `Telemetry Endpoint malformed. Received hostname: ${this.endpoint.hostname}, pathname: ${this.endpoint.pathname}`);
|
|
74
|
+
}
|
|
75
|
+
this.ioHelper = api_private_1.IoHelper.fromActionAwareIoHost(props.ioHost);
|
|
76
|
+
this.senderPath = (props.resolveSender ?? resolveSenderPath)();
|
|
77
|
+
this.proxyUrl = props.proxyUrl;
|
|
78
|
+
this.caBundlePath = props.caBundlePath;
|
|
79
|
+
// Batch events every 30 seconds
|
|
80
|
+
setInterval(() => this.flush(), 30000).unref();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Add an event to the collection.
|
|
84
|
+
*/
|
|
85
|
+
async emit(event) {
|
|
86
|
+
this.events.push(event);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Hand whatever has accumulated to a detached sender.
|
|
90
|
+
*
|
|
91
|
+
* Clears the batch either way: delivery is one-shot, the process that would retry has usually
|
|
92
|
+
* exited, and retaining the events would just re-report the failure and regrow the batch every 30s.
|
|
93
|
+
* This is the single place delivery failures are handled; `dispatch` reports them by throwing.
|
|
94
|
+
*/
|
|
95
|
+
async flush() {
|
|
96
|
+
if (this.events.length === 0) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const batch = this.events;
|
|
100
|
+
this.events = [];
|
|
101
|
+
try {
|
|
102
|
+
await this.dispatch(this.endpoint, { events: batch });
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
// Both hand-off failures arrive here: no sender on disk, and a payload write or spawn that
|
|
106
|
+
// throws. Nothing retries and no fallback runs, so report how much was lost, not only why.
|
|
107
|
+
await this.ioHelper.defaults.trace(`Failed to send telemetry event: ${e.message}. Dropped ${batch.length} event(s).`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Hand the batch to a detached sender process.
|
|
112
|
+
*
|
|
113
|
+
* Throws if the batch could not be handed over.
|
|
114
|
+
*/
|
|
115
|
+
async dispatch(url, body) {
|
|
116
|
+
if (!this.senderPath) {
|
|
117
|
+
throw new api_private_error_1.ToolkitError('SenderNotFound', `Unable to locate the telemetry sender at ${SENDER_ENTRY_POINT}`);
|
|
118
|
+
}
|
|
119
|
+
const config = {
|
|
120
|
+
endpoint: url.href,
|
|
121
|
+
body,
|
|
122
|
+
proxyUrl: this.proxyUrl,
|
|
123
|
+
caBundlePath: this.caBundlePath,
|
|
124
|
+
};
|
|
125
|
+
const payload = JSON.stringify(config);
|
|
126
|
+
// A file rather than the child's stdin: writing to stdin blocks the parent once the payload
|
|
127
|
+
// outgrows the OS pipe buffer, which is the wait this sink exists to avoid.
|
|
128
|
+
const payloadPath = path.join(os.tmpdir(), `cdk-telemetry-${process.pid}-${(0, node_crypto_1.randomUUID)()}.json`);
|
|
129
|
+
try {
|
|
130
|
+
fs.writeFileSync(payloadPath, payload, { encoding: 'utf-8', mode: 0o600 });
|
|
131
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [this.senderPath, payloadPath], {
|
|
132
|
+
detached: true,
|
|
133
|
+
// Pass the child's diagnostics through only when asked; otherwise nothing reads them.
|
|
134
|
+
stdio: senderDebugEnabled() ? ['ignore', 'ignore', 'inherit'] : 'ignore',
|
|
135
|
+
windowsHide: true,
|
|
136
|
+
shell: false,
|
|
137
|
+
// Do not hold a reference to the user's working directory; they may want to delete it.
|
|
138
|
+
cwd: os.tmpdir(),
|
|
139
|
+
});
|
|
140
|
+
// Fires after the CLI may already have exited, so it cannot go through the IoHost. Still the
|
|
141
|
+
// only notification for a spawn that is refused after this method returns.
|
|
142
|
+
child.on('error', (e) => {
|
|
143
|
+
debugTrace(`failed to spawn sender: ${e.message}`);
|
|
144
|
+
tryUnlink(payloadPath);
|
|
145
|
+
});
|
|
146
|
+
// Node reports a refused spawn (ENOENT, EACCES, EMFILE) on that `error` event, which fires
|
|
147
|
+
// after this method has already returned -- it does NOT throw here. libuv does leave `pid`
|
|
148
|
+
// unset synchronously though, so this is the one point where the failure can still be reported
|
|
149
|
+
// as one. Without it the batch is counted as handed off and traced with `pid undefined`.
|
|
150
|
+
if (child.pid === undefined) {
|
|
151
|
+
throw new api_private_error_1.ToolkitError('SpawnRefused', 'the sender process was never created');
|
|
152
|
+
}
|
|
153
|
+
child.unref();
|
|
154
|
+
await this.ioHelper.defaults.trace(`${exports.DISPATCHED_TRACE} (pid ${child.pid}, ${Buffer.byteLength(payload)} bytes)`);
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
tryUnlink(payloadPath);
|
|
158
|
+
throw new api_private_error_1.ToolkitError('DispatchFailed', `Spawning a sender for POST ${url.hostname}${url.pathname} failed: ${e.message}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.SubprocessTelemetrySink = SubprocessTelemetrySink;
|
|
163
|
+
/**
|
|
164
|
+
* Locate the bundled sender entry point inside this package.
|
|
165
|
+
*
|
|
166
|
+
* Walks up to the package root, which works both from `lib/` in source and from the released bundle.
|
|
167
|
+
* `process.argv[1]` is deliberately NOT used: it may be the `.bin/cdk` symlink, the `cdk` alias
|
|
168
|
+
* package's wrapper, or -- when the CLI is driven programmatically -- somebody else's script.
|
|
169
|
+
*
|
|
170
|
+
* Returns undefined if the entry point is not on disk, in which case telemetry is skipped.
|
|
171
|
+
*/
|
|
172
|
+
function resolveSenderPath() {
|
|
173
|
+
const root = (0, root_dir_1.cliRootDir)(false);
|
|
174
|
+
if (!root) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const senderPath = path.join(root, SENDER_ENTRY_POINT);
|
|
178
|
+
return fs.existsSync(senderPath) ? senderPath : undefined;
|
|
179
|
+
}
|
|
180
|
+
function tryUnlink(filePath) {
|
|
181
|
+
try {
|
|
182
|
+
fs.unlinkSync(filePath);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Nothing useful to do about it; the OS cleans its own temp directory.
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Whether the user asked to see the sender's diagnostics.
|
|
190
|
+
*/
|
|
191
|
+
function senderDebugEnabled() {
|
|
192
|
+
return process.env.CDK_TELEMETRY_SENDER_DEBUG === '1';
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Diagnostics for failures that surface after the CLI may already have exited, so they cannot go
|
|
196
|
+
* through the IoHost. Gated behind the same variable as the sender's own traces.
|
|
197
|
+
*/
|
|
198
|
+
function debugTrace(message) {
|
|
199
|
+
if (!senderDebugEnabled()) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
fs.writeSync(2, `[cdk-telemetry-dispatch] ${message}\n`);
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Diagnostics must never be the reason anything fails.
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VicHJvY2Vzcy1zaW5rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3VicHJvY2Vzcy1zaW5rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1LQUFtSztBQUNuSywyREFBMkM7QUFDM0MsNkNBQXlDO0FBQ3pDLDRDQUE4QjtBQUM5Qiw0Q0FBOEI7QUFDOUIsZ0RBQWtDO0FBQ2xDLHNEQUFnRDtBQUNoRCxrRUFBMEQ7QUFFMUQsNkNBQTRDO0FBTTVDOztHQUVHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFFcEY7O0dBRUc7QUFDVSxRQUFBLGdCQUFnQixHQUFHLHNCQUFzQixDQUFDO0FBeUN2RDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsdUJBQXVCO0lBQzFCLE1BQU0sR0FBc0IsRUFBRSxDQUFDO0lBQy9CLFFBQVEsQ0FBTTtJQUNkLFFBQVEsQ0FBVztJQUNuQixVQUFVLENBQVU7SUFDcEIsUUFBUSxDQUFVO0lBQ2xCLFlBQVksQ0FBVTtJQUU5QixZQUFtQixLQUFtQztRQUNwRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV4QyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3ZELE1BQU0sSUFBSSxnQ0FBWSxDQUFDLG1CQUFtQixFQUFFLG9EQUFvRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsZUFBZSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDakssQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsc0JBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksaUJBQWlCLENBQUMsRUFBRSxDQUFDO1FBQy9ELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztRQUMvQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUM7UUFFdkMsZ0NBQWdDO1FBQ2hDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDakQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFzQjtRQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksS0FBSyxDQUFDLEtBQUs7UUFDaEIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM3QixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDMUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFFakIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztZQUNoQiwyRkFBMkY7WUFDM0YsMkZBQTJGO1lBQzNGLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUMsT0FBTyxhQUFhLEtBQUssQ0FBQyxNQUFNLFlBQVksQ0FBQyxDQUFDO1FBQ3hILENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBUSxFQUFFLElBQW9CO1FBQ25ELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLGdDQUFZLENBQUMsZ0JBQWdCLEVBQUUsNENBQTRDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUM3RyxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQTBCO1lBQ3BDLFFBQVEsRUFBRSxHQUFHLENBQUMsSUFBSTtZQUNsQixJQUFJO1lBQ0osUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1lBQ3ZCLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtTQUNoQyxDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV2Qyw0RkFBNEY7UUFDNUYsNEVBQTRFO1FBQzVFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLGlCQUFpQixPQUFPLENBQUMsR0FBRyxJQUFJLElBQUEsd0JBQVUsR0FBRSxPQUFPLENBQUMsQ0FBQztRQUVoRyxJQUFJLENBQUM7WUFDSCxFQUFFLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBRTNFLE1BQU0sS0FBSyxHQUFHLElBQUEsMEJBQUssRUFBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsRUFBRTtnQkFDcEUsUUFBUSxFQUFFLElBQUk7Z0JBQ2Qsc0ZBQXNGO2dCQUN0RixLQUFLLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRO2dCQUN4RSxXQUFXLEVBQUUsSUFBSTtnQkFDakIsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osdUZBQXVGO2dCQUN2RixHQUFHLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRTthQUNqQixDQUFDLENBQUM7WUFFSCw2RkFBNkY7WUFDN0YsMkVBQTJFO1lBQzNFLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBUSxFQUFFLEVBQUU7Z0JBQzdCLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQ25ELFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN6QixDQUFDLENBQUMsQ0FBQztZQUVILDJGQUEyRjtZQUMzRiwyRkFBMkY7WUFDM0YsK0ZBQStGO1lBQy9GLHlGQUF5RjtZQUN6RixJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSxnQ0FBWSxDQUFDLGNBQWMsRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDO1lBQ2pGLENBQUM7WUFFRCxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFFZCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLHdCQUFnQixTQUFTLEtBQUssQ0FBQyxHQUFHLEtBQUssTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDcEgsQ0FBQztRQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7WUFDaEIsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZCLE1BQU0sSUFBSSxnQ0FBWSxDQUFDLGdCQUFnQixFQUFFLDhCQUE4QixHQUFHLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxRQUFRLFlBQVksQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0gsQ0FBQztJQUNILENBQUM7Q0FDRjtBQWpIRCwwREFpSEM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQVMsaUJBQWlCO0lBQ3hCLE1BQU0sSUFBSSxHQUFHLElBQUEscUJBQVUsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUMvQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDVixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN2RCxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVELENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxRQUFnQjtJQUNqQyxJQUFJLENBQUM7UUFDSCxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCx1RUFBdUU7SUFDekUsQ0FBQztBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsa0JBQWtCO0lBQ3pCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsS0FBSyxHQUFHLENBQUM7QUFDeEQsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsVUFBVSxDQUFDLE9BQWU7SUFDakMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztRQUMxQixPQUFPO0lBQ1QsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLDRCQUE0QixPQUFPLElBQUksQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCx1REFBdUQ7SUFDekQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1pbXBvcnRzIC0tIHRoZSBkZXRhY2hlZCBzZW5kZXIgbXVzdCBvdXRsaXZlIHRoZSBDTEk7IHJ1bi9ydW5TeW5jIGZyb20gdGhlIHN1YnByb2Nlc3MgdG9vbCBtb25pdG9yIHRoZSBjaGlsZCB0byBjb21wbGV0aW9uXG5pbXBvcnQgeyBzcGF3biB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdub2RlOm9zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IElvSGVscGVyIH0gZnJvbSAnLi4vLi4vLi4vYXBpLXByaXZhdGUnO1xuaW1wb3J0IHsgVG9vbGtpdEVycm9yIH0gZnJvbSAnLi4vLi4vLi4vYXBpLXByaXZhdGUtZXJyb3InO1xuaW1wb3J0IHR5cGUgeyBJSW9Ib3N0IH0gZnJvbSAnLi4vLi4vaW8taG9zdCc7XG5pbXBvcnQgeyBjbGlSb290RGlyIH0gZnJvbSAnLi4vLi4vcm9vdC1kaXInO1xuaW1wb3J0IHR5cGUgeyBUZWxlbWV0cnlCYXRjaCB9IGZyb20gJy4uL3Bvc3QtdGVsZW1ldHJ5JztcbmltcG9ydCB0eXBlIHsgVGVsZW1ldHJ5U2NoZW1hIH0gZnJvbSAnLi4vc2NoZW1hJztcbmltcG9ydCB0eXBlIHsgVGVsZW1ldHJ5U2VuZGVyQ29uZmlnIH0gZnJvbSAnLi4vc2VuZGVyJztcbmltcG9ydCB0eXBlIHsgSVRlbGVtZXRyeVNpbmsgfSBmcm9tICcuL3NpbmstaW50ZXJmYWNlJztcblxuLyoqXG4gKiBUaGUgYnVuZGxlZCBzZW5kZXIgZW50cnkgcG9pbnQsIHJlbGF0aXZlIHRvIHRoaXMgcGFja2FnZSdzIHJvb3QuXG4gKi9cbmNvbnN0IFNFTkRFUl9FTlRSWV9QT0lOVCA9IHBhdGguam9pbignbGliJywgJ2NsaScsICd0ZWxlbWV0cnknLCAnc2VuZGVyLWJ1bmRsZS5qcycpO1xuXG4vKipcbiAqIFJlcG9ydHMgYSBzdWNjZXNzZnVsIGhhbmQtb2ZmLCBOT1QgYSBzdWNjZXNzZnVsIGRlbGl2ZXJ5LlxuICovXG5leHBvcnQgY29uc3QgRElTUEFUQ0hFRF9UUkFDRSA9ICdUZWxlbWV0cnkgZGlzcGF0Y2hlZCc7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIHN1YnByb2Nlc3MgdGVsZW1ldHJ5IHNpbmsuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VicHJvY2Vzc1RlbGVtZXRyeVNpbmtQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgZXh0ZXJuYWwgZW5kcG9pbnQgdG8gaGl0XG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVyZSBtZXNzYWdlcyBhcmUgZ29pbmcgdG8gYmUgc2VudFxuICAgKi9cbiAgcmVhZG9ubHkgaW9Ib3N0OiBJSW9Ib3N0O1xuXG4gIC8qKlxuICAgKiBQcm94eSB0aGUgc2VuZGVyIHNob3VsZCByb3V0ZSB0aHJvdWdoLCBhcyBjb25maWd1cmVkIGJ5IGAtLXByb3h5YCBvciB0aGUgYHByb3h5YCBzZXR0aW5nLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJlc29sdmVkIGZyb20gdGhlIGVudmlyb25tZW50IGJ5IHRoZSBzZW5kZXIsIGFzIGBwcm94eS1hZ2VudGAgZG9lcyBmb3IgdGhlIHJlc3Qgb2YgdGhlIENMSVxuICAgKi9cbiAgcmVhZG9ubHkgcHJveHlVcmw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gdGhlIENBIGJ1bmRsZSB0byB0cnVzdCwgYXMgY29uZmlndXJlZCBieSBgLS1jYS1idW5kbGUtcGF0aGAgb3IgYEFXU19DQV9CVU5ETEVgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG9ubHkgdGhlIHN5c3RlbSB0cnVzdCBzdG9yZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FCdW5kbGVQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBIb3cgdG8gbG9jYXRlIHRoZSBidW5kbGVkIHNlbmRlciBlbnRyeSBwb2ludC5cbiAgICpcbiAgICogSW5qZWN0YWJsZSBzbyBhIHRlc3QgY2FuIGV4ZXJjaXNlIHRoZSBtaXNzaW5nLXNlbmRlciBwYXRoIHdpdGhvdXQgcmVhY2hpbmcgaW50byB0aGlzIG9iamVjdCdzXG4gICAqIHByaXZhdGVzOyByZXR1cm5pbmcgdW5kZWZpbmVkIGlzIHdoYXQgXCJub3Qgb24gZGlza1wiIGxvb2tzIGxpa2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbG9va2VkIHVwIHJlbGF0aXZlIHRvIHRoaXMgcGFja2FnZSdzIHJvb3RcbiAgICovXG4gIHJlYWRvbmx5IHJlc29sdmVTZW5kZXI/OiAoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQSB0ZWxlbWV0cnkgc2luayB0aGF0IGRlbGl2ZXJzIGV2ZW50cyBmcm9tIGEgZGV0YWNoZWQgY2hpbGQgcHJvY2Vzcy5cbiAqXG4gKiBFdmVudHMgYXJlIHdyaXR0ZW4gdG8gYSB0ZW1wb3JhcnkgZmlsZSBhbmQgaGFuZGVkIHRvIGEgY2hpbGQgdGhhdCBvdXRsaXZlcyB1cywgc28gdGhlIENMSSBjYW4gZXhpdFxuICogaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nIG9uIHRoZSBuZXR3b3JrLiBOb3RoaW5nIGhlcmUgZXZlciBsZWFybnMgd2hldGhlciBkZWxpdmVyeSBzdWNjZWVkZWQuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGRvZXMgbm90IGNoZWNrIGNvbm5lY3Rpdml0eSBmaXJzdDogdGhhdCBjaGVjayB3b3VsZCBpdHNlbGYgYmUgYSBuZXR3b3JrIGNhbGwgb24gdGhlXG4gKiBleGl0IHBhdGgsIHdoaWNoIGlzIHdoYXQgdGhpcyBzaW5rIGV4aXN0cyB0byBhdm9pZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFN1YnByb2Nlc3NUZWxlbWV0cnlTaW5rIGltcGxlbWVudHMgSVRlbGVtZXRyeVNpbmsge1xuICBwcml2YXRlIGV2ZW50czogVGVsZW1ldHJ5U2NoZW1hW10gPSBbXTtcbiAgcHJpdmF0ZSBlbmRwb2ludDogVVJMO1xuICBwcml2YXRlIGlvSGVscGVyOiBJb0hlbHBlcjtcbiAgcHJpdmF0ZSBzZW5kZXJQYXRoPzogc3RyaW5nO1xuICBwcml2YXRlIHByb3h5VXJsPzogc3RyaW5nO1xuICBwcml2YXRlIGNhQnVuZGxlUGF0aD86IHN0cmluZztcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IFN1YnByb2Nlc3NUZWxlbWV0cnlTaW5rUHJvcHMpIHtcbiAgICB0aGlzLmVuZHBvaW50ID0gbmV3IFVSTChwcm9wcy5lbmRwb2ludCk7XG5cbiAgICBpZiAoIXRoaXMuZW5kcG9pbnQuaG9zdG5hbWUgfHwgIXRoaXMuZW5kcG9pbnQucGF0aG5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ01hbGZvcm1lZEVuZHBvaW50JywgYFRlbGVtZXRyeSBFbmRwb2ludCBtYWxmb3JtZWQuIFJlY2VpdmVkIGhvc3RuYW1lOiAke3RoaXMuZW5kcG9pbnQuaG9zdG5hbWV9LCBwYXRobmFtZTogJHt0aGlzLmVuZHBvaW50LnBhdGhuYW1lfWApO1xuICAgIH1cblxuICAgIHRoaXMuaW9IZWxwZXIgPSBJb0hlbHBlci5mcm9tQWN0aW9uQXdhcmVJb0hvc3QocHJvcHMuaW9Ib3N0KTtcbiAgICB0aGlzLnNlbmRlclBhdGggPSAocHJvcHMucmVzb2x2ZVNlbmRlciA/PyByZXNvbHZlU2VuZGVyUGF0aCkoKTtcbiAgICB0aGlzLnByb3h5VXJsID0gcHJvcHMucHJveHlVcmw7XG4gICAgdGhpcy5jYUJ1bmRsZVBhdGggPSBwcm9wcy5jYUJ1bmRsZVBhdGg7XG5cbiAgICAvLyBCYXRjaCBldmVudHMgZXZlcnkgMzAgc2Vjb25kc1xuICAgIHNldEludGVydmFsKCgpID0+IHRoaXMuZmx1c2goKSwgMzAwMDApLnVucmVmKCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFuIGV2ZW50IHRvIHRoZSBjb2xsZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGVtaXQoZXZlbnQ6IFRlbGVtZXRyeVNjaGVtYSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZXZlbnRzLnB1c2goZXZlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmQgd2hhdGV2ZXIgaGFzIGFjY3VtdWxhdGVkIHRvIGEgZGV0YWNoZWQgc2VuZGVyLlxuICAgKlxuICAgKiBDbGVhcnMgdGhlIGJhdGNoIGVpdGhlciB3YXk6IGRlbGl2ZXJ5IGlzIG9uZS1zaG90LCB0aGUgcHJvY2VzcyB0aGF0IHdvdWxkIHJldHJ5IGhhcyB1c3VhbGx5XG4gICAqIGV4aXRlZCwgYW5kIHJldGFpbmluZyB0aGUgZXZlbnRzIHdvdWxkIGp1c3QgcmUtcmVwb3J0IHRoZSBmYWlsdXJlIGFuZCByZWdyb3cgdGhlIGJhdGNoIGV2ZXJ5IDMwcy5cbiAgICogVGhpcyBpcyB0aGUgc2luZ2xlIHBsYWNlIGRlbGl2ZXJ5IGZhaWx1cmVzIGFyZSBoYW5kbGVkOyBgZGlzcGF0Y2hgIHJlcG9ydHMgdGhlbSBieSB0aHJvd2luZy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBmbHVzaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5ldmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmV2ZW50cztcbiAgICB0aGlzLmV2ZW50cyA9IFtdO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2godGhpcy5lbmRwb2ludCwgeyBldmVudHM6IGJhdGNoIH0pO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgLy8gQm90aCBoYW5kLW9mZiBmYWlsdXJlcyBhcnJpdmUgaGVyZTogbm8gc2VuZGVyIG9uIGRpc2ssIGFuZCBhIHBheWxvYWQgd3JpdGUgb3Igc3Bhd24gdGhhdFxuICAgICAgLy8gdGhyb3dzLiBOb3RoaW5nIHJldHJpZXMgYW5kIG5vIGZhbGxiYWNrIHJ1bnMsIHNvIHJlcG9ydCBob3cgbXVjaCB3YXMgbG9zdCwgbm90IG9ubHkgd2h5LlxuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5kZWZhdWx0cy50cmFjZShgRmFpbGVkIHRvIHNlbmQgdGVsZW1ldHJ5IGV2ZW50OiAke2UubWVzc2FnZX0uIERyb3BwZWQgJHtiYXRjaC5sZW5ndGh9IGV2ZW50KHMpLmApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kIHRoZSBiYXRjaCB0byBhIGRldGFjaGVkIHNlbmRlciBwcm9jZXNzLlxuICAgKlxuICAgKiBUaHJvd3MgaWYgdGhlIGJhdGNoIGNvdWxkIG5vdCBiZSBoYW5kZWQgb3Zlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGlzcGF0Y2godXJsOiBVUkwsIGJvZHk6IFRlbGVtZXRyeUJhdGNoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnNlbmRlclBhdGgpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1NlbmRlck5vdEZvdW5kJywgYFVuYWJsZSB0byBsb2NhdGUgdGhlIHRlbGVtZXRyeSBzZW5kZXIgYXQgJHtTRU5ERVJfRU5UUllfUE9JTlR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnOiBUZWxlbWV0cnlTZW5kZXJDb25maWcgPSB7XG4gICAgICBlbmRwb2ludDogdXJsLmhyZWYsXG4gICAgICBib2R5LFxuICAgICAgcHJveHlVcmw6IHRoaXMucHJveHlVcmwsXG4gICAgICBjYUJ1bmRsZVBhdGg6IHRoaXMuY2FCdW5kbGVQYXRoLFxuICAgIH07XG4gICAgY29uc3QgcGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KGNvbmZpZyk7XG5cbiAgICAvLyBBIGZpbGUgcmF0aGVyIHRoYW4gdGhlIGNoaWxkJ3Mgc3RkaW46IHdyaXRpbmcgdG8gc3RkaW4gYmxvY2tzIHRoZSBwYXJlbnQgb25jZSB0aGUgcGF5bG9hZFxuICAgIC8vIG91dGdyb3dzIHRoZSBPUyBwaXBlIGJ1ZmZlciwgd2hpY2ggaXMgdGhlIHdhaXQgdGhpcyBzaW5rIGV4aXN0cyB0byBhdm9pZC5cbiAgICBjb25zdCBwYXlsb2FkUGF0aCA9IHBhdGguam9pbihvcy50bXBkaXIoKSwgYGNkay10ZWxlbWV0cnktJHtwcm9jZXNzLnBpZH0tJHtyYW5kb21VVUlEKCl9Lmpzb25gKTtcblxuICAgIHRyeSB7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKHBheWxvYWRQYXRoLCBwYXlsb2FkLCB7IGVuY29kaW5nOiAndXRmLTgnLCBtb2RlOiAwbzYwMCB9KTtcblxuICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bihwcm9jZXNzLmV4ZWNQYXRoLCBbdGhpcy5zZW5kZXJQYXRoLCBwYXlsb2FkUGF0aF0sIHtcbiAgICAgICAgZGV0YWNoZWQ6IHRydWUsXG4gICAgICAgIC8vIFBhc3MgdGhlIGNoaWxkJ3MgZGlhZ25vc3RpY3MgdGhyb3VnaCBvbmx5IHdoZW4gYXNrZWQ7IG90aGVyd2lzZSBub3RoaW5nIHJlYWRzIHRoZW0uXG4gICAgICAgIHN0ZGlvOiBzZW5kZXJEZWJ1Z0VuYWJsZWQoKSA/IFsnaWdub3JlJywgJ2lnbm9yZScsICdpbmhlcml0J10gOiAnaWdub3JlJyxcbiAgICAgICAgd2luZG93c0hpZGU6IHRydWUsXG4gICAgICAgIHNoZWxsOiBmYWxzZSxcbiAgICAgICAgLy8gRG8gbm90IGhvbGQgYSByZWZlcmVuY2UgdG8gdGhlIHVzZXIncyB3b3JraW5nIGRpcmVjdG9yeTsgdGhleSBtYXkgd2FudCB0byBkZWxldGUgaXQuXG4gICAgICAgIGN3ZDogb3MudG1wZGlyKCksXG4gICAgICB9KTtcblxuICAgICAgLy8gRmlyZXMgYWZ0ZXIgdGhlIENMSSBtYXkgYWxyZWFkeSBoYXZlIGV4aXRlZCwgc28gaXQgY2Fubm90IGdvIHRocm91Z2ggdGhlIElvSG9zdC4gU3RpbGwgdGhlXG4gICAgICAvLyBvbmx5IG5vdGlmaWNhdGlvbiBmb3IgYSBzcGF3biB0aGF0IGlzIHJlZnVzZWQgYWZ0ZXIgdGhpcyBtZXRob2QgcmV0dXJucy5cbiAgICAgIGNoaWxkLm9uKCdlcnJvcicsIChlOiBFcnJvcikgPT4ge1xuICAgICAgICBkZWJ1Z1RyYWNlKGBmYWlsZWQgdG8gc3Bhd24gc2VuZGVyOiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgdHJ5VW5saW5rKHBheWxvYWRQYXRoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBOb2RlIHJlcG9ydHMgYSByZWZ1c2VkIHNwYXduIChFTk9FTlQsIEVBQ0NFUywgRU1GSUxFKSBvbiB0aGF0IGBlcnJvcmAgZXZlbnQsIHdoaWNoIGZpcmVzXG4gICAgICAvLyBhZnRlciB0aGlzIG1ldGhvZCBoYXMgYWxyZWFkeSByZXR1cm5lZCAtLSBpdCBkb2VzIE5PVCB0aHJvdyBoZXJlLiBsaWJ1diBkb2VzIGxlYXZlIGBwaWRgXG4gICAgICAvLyB1bnNldCBzeW5jaHJvbm91c2x5IHRob3VnaCwgc28gdGhpcyBpcyB0aGUgb25lIHBvaW50IHdoZXJlIHRoZSBmYWlsdXJlIGNhbiBzdGlsbCBiZSByZXBvcnRlZFxuICAgICAgLy8gYXMgb25lLiBXaXRob3V0IGl0IHRoZSBiYXRjaCBpcyBjb3VudGVkIGFzIGhhbmRlZCBvZmYgYW5kIHRyYWNlZCB3aXRoIGBwaWQgdW5kZWZpbmVkYC5cbiAgICAgIGlmIChjaGlsZC5waWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdTcGF3blJlZnVzZWQnLCAndGhlIHNlbmRlciBwcm9jZXNzIHdhcyBuZXZlciBjcmVhdGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGNoaWxkLnVucmVmKCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIuZGVmYXVsdHMudHJhY2UoYCR7RElTUEFUQ0hFRF9UUkFDRX0gKHBpZCAke2NoaWxkLnBpZH0sICR7QnVmZmVyLmJ5dGVMZW5ndGgocGF5bG9hZCl9IGJ5dGVzKWApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdHJ5VW5saW5rKHBheWxvYWRQYXRoKTtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0Rpc3BhdGNoRmFpbGVkJywgYFNwYXduaW5nIGEgc2VuZGVyIGZvciBQT1NUICR7dXJsLmhvc3RuYW1lfSR7dXJsLnBhdGhuYW1lfSBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIExvY2F0ZSB0aGUgYnVuZGxlZCBzZW5kZXIgZW50cnkgcG9pbnQgaW5zaWRlIHRoaXMgcGFja2FnZS5cbiAqXG4gKiBXYWxrcyB1cCB0byB0aGUgcGFja2FnZSByb290LCB3aGljaCB3b3JrcyBib3RoIGZyb20gYGxpYi9gIGluIHNvdXJjZSBhbmQgZnJvbSB0aGUgcmVsZWFzZWQgYnVuZGxlLlxuICogYHByb2Nlc3MuYXJndlsxXWAgaXMgZGVsaWJlcmF0ZWx5IE5PVCB1c2VkOiBpdCBtYXkgYmUgdGhlIGAuYmluL2Nka2Agc3ltbGluaywgdGhlIGBjZGtgIGFsaWFzXG4gKiBwYWNrYWdlJ3Mgd3JhcHBlciwgb3IgLS0gd2hlbiB0aGUgQ0xJIGlzIGRyaXZlbiBwcm9ncmFtbWF0aWNhbGx5IC0tIHNvbWVib2R5IGVsc2UncyBzY3JpcHQuXG4gKlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIGVudHJ5IHBvaW50IGlzIG5vdCBvbiBkaXNrLCBpbiB3aGljaCBjYXNlIHRlbGVtZXRyeSBpcyBza2lwcGVkLlxuICovXG5mdW5jdGlvbiByZXNvbHZlU2VuZGVyUGF0aCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCByb290ID0gY2xpUm9vdERpcihmYWxzZSk7XG4gIGlmICghcm9vdCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBzZW5kZXJQYXRoID0gcGF0aC5qb2luKHJvb3QsIFNFTkRFUl9FTlRSWV9QT0lOVCk7XG4gIHJldHVybiBmcy5leGlzdHNTeW5jKHNlbmRlclBhdGgpID8gc2VuZGVyUGF0aCA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gdHJ5VW5saW5rKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBmcy51bmxpbmtTeW5jKGZpbGVQYXRoKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gTm90aGluZyB1c2VmdWwgdG8gZG8gYWJvdXQgaXQ7IHRoZSBPUyBjbGVhbnMgaXRzIG93biB0ZW1wIGRpcmVjdG9yeS5cbiAgfVxufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIHVzZXIgYXNrZWQgdG8gc2VlIHRoZSBzZW5kZXIncyBkaWFnbm9zdGljcy5cbiAqL1xuZnVuY3Rpb24gc2VuZGVyRGVidWdFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuQ0RLX1RFTEVNRVRSWV9TRU5ERVJfREVCVUcgPT09ICcxJztcbn1cblxuLyoqXG4gKiBEaWFnbm9zdGljcyBmb3IgZmFpbHVyZXMgdGhhdCBzdXJmYWNlIGFmdGVyIHRoZSBDTEkgbWF5IGFscmVhZHkgaGF2ZSBleGl0ZWQsIHNvIHRoZXkgY2Fubm90IGdvXG4gKiB0aHJvdWdoIHRoZSBJb0hvc3QuIEdhdGVkIGJlaGluZCB0aGUgc2FtZSB2YXJpYWJsZSBhcyB0aGUgc2VuZGVyJ3Mgb3duIHRyYWNlcy5cbiAqL1xuZnVuY3Rpb24gZGVidWdUcmFjZShtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFzZW5kZXJEZWJ1Z0VuYWJsZWQoKSkge1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGZzLndyaXRlU3luYygyLCBgW2Nkay10ZWxlbWV0cnktZGlzcGF0Y2hdICR7bWVzc2FnZX1cXG5gKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gRGlhZ25vc3RpY3MgbXVzdCBuZXZlciBiZSB0aGUgcmVhc29uIGFueXRoaW5nIGZhaWxzLlxuICB9XG59XG4iXX0=
|