UNPKG

aws-cdk

Version:

AWS CDK Toolkit CLI, the command line tool for CDK apps

209 lines • 26.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.SubprocessTelemetrySink = exports.DISPATCHED_TRACE = void 0; // 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 const node_child_process_1 = require("node:child_process"); const node_crypto_1 = require("node:crypto"); const fs = __importStar(require("node:fs")); const os = __importStar(require("node:os")); const path = __importStar(require("node:path")); const api_private_1 = require("../../../api-private"); const api_private_error_1 = require("../../../api-private-error"); const root_dir_1 = require("../../root-dir"); /** * The bundled sender entry point, relative to this package's root. */ const SENDER_ENTRY_POINT = path.join('lib', 'cli', 'telemetry', 'sender-bundle.js'); /** * Reports a successful hand-off, NOT a successful delivery. */ exports.DISPATCHED_TRACE = 'Telemetry dispatched'; /** * A telemetry sink that delivers events from a detached child process. * * Events are written to a temporary file and handed to a child that outlives us, so the CLI can exit * immediately instead of waiting on the network. Nothing here ever learns whether delivery succeeded. * * Deliberately does not check connectivity first: that check would itself be a network call on the * exit path, which is what this sink exists to avoid. */ class SubprocessTelemetrySink { events = []; endpoint; ioHelper; senderPath; proxyUrl; caBundlePath; constructor(props) { this.endpoint = new URL(props.endpoint); if (!this.endpoint.hostname || !this.endpoint.pathname) { throw new api_private_error_1.ToolkitError('MalformedEndpoint', `Telemetry Endpoint malformed. Received hostname: ${this.endpoint.hostname}, pathname: ${this.endpoint.pathname}`); } this.ioHelper = api_private_1.IoHelper.fromActionAwareIoHost(props.ioHost); this.senderPath = (props.resolveSender ?? resolveSenderPath)(); this.proxyUrl = props.proxyUrl; this.caBundlePath = props.caBundlePath; // Batch events every 30 seconds setInterval(() => this.flush(), 30000).unref(); } /** * Add an event to the collection. */ async emit(event) { this.events.push(event); } /** * Hand whatever has accumulated to a detached sender. * * Clears the batch either way: delivery is one-shot, the process that would retry has usually * exited, and retaining the events would just re-report the failure and regrow the batch every 30s. * This is the single place delivery failures are handled; `dispatch` reports them by throwing. */ async flush() { if (this.events.length === 0) { return; } const batch = this.events; this.events = []; try { await this.dispatch(this.endpoint, { events: batch }); } catch (e) { // Both hand-off failures arrive here: no sender on disk, and a payload write or spawn that // throws. Nothing retries and no fallback runs, so report how much was lost, not only why. await this.ioHelper.defaults.trace(`Failed to send telemetry event: ${e.message}. Dropped ${batch.length} event(s).`); } } /** * Hand the batch to a detached sender process. * * Throws if the batch could not be handed over. */ async dispatch(url, body) { if (!this.senderPath) { throw new api_private_error_1.ToolkitError('SenderNotFound', `Unable to locate the telemetry sender at ${SENDER_ENTRY_POINT}`); } const config = { endpoint: url.href, body, proxyUrl: this.proxyUrl, caBundlePath: this.caBundlePath, }; const payload = JSON.stringify(config); // A file rather than the child's stdin: writing to stdin blocks the parent once the payload // outgrows the OS pipe buffer, which is the wait this sink exists to avoid. const payloadPath = path.join(os.tmpdir(), `cdk-telemetry-${process.pid}-${(0, node_crypto_1.randomUUID)()}.json`); try { fs.writeFileSync(payloadPath, payload, { encoding: 'utf-8', mode: 0o600 }); const child = (0, node_child_process_1.spawn)(process.execPath, [this.senderPath, payloadPath], { detached: true, // Pass the child's diagnostics through only when asked; otherwise nothing reads them. stdio: senderDebugEnabled() ? ['ignore', 'ignore', 'inherit'] : 'ignore', windowsHide: true, shell: false, // Do not hold a reference to the user's working directory; they may want to delete it. cwd: os.tmpdir(), }); // Fires after the CLI may already have exited, so it cannot go through the IoHost. Still the // only notification for a spawn that is refused after this method returns. child.on('error', (e) => { debugTrace(`failed to spawn sender: ${e.message}`); tryUnlink(payloadPath); }); // Node reports a refused spawn (ENOENT, EACCES, EMFILE) on that `error` event, which fires // after this method has already returned -- it does NOT throw here. libuv does leave `pid` // unset synchronously though, so this is the one point where the failure can still be reported // as one. Without it the batch is counted as handed off and traced with `pid undefined`. if (child.pid === undefined) { throw new api_private_error_1.ToolkitError('SpawnRefused', 'the sender process was never created'); } child.unref(); await this.ioHelper.defaults.trace(`${exports.DISPATCHED_TRACE} (pid ${child.pid}, ${Buffer.byteLength(payload)} bytes)`); } catch (e) { tryUnlink(payloadPath); throw new api_private_error_1.ToolkitError('DispatchFailed', `Spawning a sender for POST ${url.hostname}${url.pathname} failed: ${e.message}`); } } } exports.SubprocessTelemetrySink = SubprocessTelemetrySink; /** * Locate the bundled sender entry point inside this package. * * Walks up to the package root, which works both from `lib/` in source and from the released bundle. * `process.argv[1]` is deliberately NOT used: it may be the `.bin/cdk` symlink, the `cdk` alias * package's wrapper, or -- when the CLI is driven programmatically -- somebody else's script. * * Returns undefined if the entry point is not on disk, in which case telemetry is skipped. */ function resolveSenderPath() { const root = (0, root_dir_1.cliRootDir)(false); if (!root) { return undefined; } const senderPath = path.join(root, SENDER_ENTRY_POINT); return fs.existsSync(senderPath) ? senderPath : undefined; } function tryUnlink(filePath) { try { fs.unlinkSync(filePath); } catch { // Nothing useful to do about it; the OS cleans its own temp directory. } } /** * Whether the user asked to see the sender's diagnostics. */ function senderDebugEnabled() { return process.env.CDK_TELEMETRY_SENDER_DEBUG === '1'; } /** * Diagnostics for failures that surface after the CLI may already have exited, so they cannot go * through the IoHost. Gated behind the same variable as the sender's own traces. */ function debugTrace(message) { if (!senderDebugEnabled()) { return; } try { fs.writeSync(2, `[cdk-telemetry-dispatch] ${message}\n`); } catch { // Diagnostics must never be the reason anything fails. } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VicHJvY2Vzcy1zaW5rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3VicHJvY2Vzcy1zaW5rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1LQUFtSztBQUNuSywyREFBMkM7QUFDM0MsNkNBQXlDO0FBQ3pDLDRDQUE4QjtBQUM5Qiw0Q0FBOEI7QUFDOUIsZ0RBQWtDO0FBQ2xDLHNEQUFnRDtBQUNoRCxrRUFBMEQ7QUFFMUQsNkNBQTRDO0FBTTVDOztHQUVHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFFcEY7O0dBRUc7QUFDVSxRQUFBLGdCQUFnQixHQUFHLHNCQUFzQixDQUFDO0FBeUN2RDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsdUJBQXVCO0lBQzFCLE1BQU0sR0FBc0IsRUFBRSxDQUFDO0lBQy9CLFFBQVEsQ0FBTTtJQUNkLFFBQVEsQ0FBVztJQUNuQixVQUFVLENBQVU7SUFDcEIsUUFBUSxDQUFVO0lBQ2xCLFlBQVksQ0FBVTtJQUU5QixZQUFtQixLQUFtQztRQUNwRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV4QyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3ZELE1BQU0sSUFBSSxnQ0FBWSxDQUFDLG1CQUFtQixFQUFFLG9EQUFvRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsZUFBZSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDakssQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsc0JBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxL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LENBQUM7UUFDVixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN2RCxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVELENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxRQUFnQjtJQUNqQyxJQUFJLENBQUM7UUFDSCxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCx1RUFBdUU7SUFDekUsQ0FBQztBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsa0JBQWtCO0lBQ3pCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsS0FBSyxHQUFHLENBQUM7QUFDeEQsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsVUFBVSxDQUFDLE9BQWU7SUFDakMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztRQUMxQixPQUFPO0lBQ1QsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLDRCQUE0QixPQUFPLElBQUksQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCx1REFBdUQ7SUFDekQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1pbXBvcnRzIC0tIHRoZSBkZXRhY2hlZCBzZW5kZXIgbXVzdCBvdXRsaXZlIHRoZSBDTEk7IHJ1bi9ydW5TeW5jIGZyb20gdGhlIHN1YnByb2Nlc3MgdG9vbCBtb25pdG9yIHRoZSBjaGlsZCB0byBjb21wbGV0aW9uXG5pbXBvcnQgeyBzcGF3biB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdub2RlOm9zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IElvSGVscGVyIH0gZnJvbSAnLi4vLi4vLi4vYXBpLXByaXZhdGUnO1xuaW1wb3J0IHsgVG9vbGtpdEVycm9yIH0gZnJvbSAnLi4vLi4vLi4vYXBpLXByaXZhdGUtZXJyb3InO1xuaW1wb3J0IHR5cGUgeyBJSW9Ib3N0IH0gZnJvbSAnLi4vLi4vaW8taG9zdCc7XG5pbXBvcnQgeyBjbGlSb290RGlyIH0gZnJvbSAnLi4vLi4vcm9vdC1kaXInO1xuaW1wb3J0IHR5cGUgeyBUZWxlbWV0cnlCYXRjaCB9IGZyb20gJy4uL3Bvc3QtdGVsZW1ldHJ5JztcbmltcG9ydCB0eXBlIHsgVGVsZW1ldHJ5U2NoZW1hIH0gZnJvbSAnLi4vc2NoZW1hJztcbmltcG9ydCB0eXBlIHsgVGVsZW1ldHJ5U2VuZGVyQ29uZmlnIH0gZnJvbSAnLi4vc2VuZGVyJztcbmltcG9ydCB0eXBlIHsgSVRlbGVtZXRyeVNpbmsgfSBmcm9tICcuL3NpbmstaW50ZXJmYWNlJztcblxuLyoqXG4gKiBUaGUgYnVuZGxlZCBzZW5kZXIgZW50cnkgcG9pbnQsIHJlbGF0aXZlIHRvIHRoaXMgcGFja2FnZSdzIHJvb3QuXG4gKi9cbmNvbnN0IFNFTkRFUl9FTlRSWV9QT0lOVCA9IHBhdGguam9pbignbGliJywgJ2NsaScsICd0ZWxlbWV0cnknLCAnc2VuZGVyLWJ1bmRsZS5qcycpO1xuXG4vKipcbiAqIFJlcG9ydHMgYSBzdWNjZXNzZnVsIGhhbmQtb2ZmLCBOT1QgYSBzdWNjZXNzZnVsIGRlbGl2ZXJ5LlxuICovXG5leHBvcnQgY29uc3QgRElTUEFUQ0hFRF9UUkFDRSA9ICdUZWxlbWV0cnkgZGlzcGF0Y2hlZCc7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIHN1YnByb2Nlc3MgdGVsZW1ldHJ5IHNpbmsuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VicHJvY2Vzc1RlbGVtZXRyeVNpbmtQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgZXh0ZXJuYWwgZW5kcG9pbnQgdG8gaGl0XG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVyZSBtZXNzYWdlcyBhcmUgZ29pbmcgdG8gYmUgc2VudFxuICAgKi9cbiAgcmVhZG9ubHkgaW9Ib3N0OiBJSW9Ib3N0O1xuXG4gIC8qKlxuICAgKiBQcm94eSB0aGUgc2VuZGVyIHNob3VsZCByb3V0ZSB0aHJvdWdoLCBhcyBjb25maWd1cmVkIGJ5IGAtLXByb3h5YCBvciB0aGUgYHByb3h5YCBzZXR0aW5nLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJlc29sdmVkIGZyb20gdGhlIGVudmlyb25tZW50IGJ5IHRoZSBzZW5kZXIsIGFzIGBwcm94eS1hZ2VudGAgZG9lcyBmb3IgdGhlIHJlc3Qgb2YgdGhlIENMSVxuICAgKi9cbiAgcmVhZG9ubHkgcHJveHlVcmw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gdGhlIENBIGJ1bmRsZSB0byB0cnVzdCwgYXMgY29uZmlndXJlZCBieSBgLS1jYS1idW5kbGUtcGF0aGAgb3IgYEFXU19DQV9CVU5ETEVgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG9ubHkgdGhlIHN5c3RlbSB0cnVzdCBzdG9yZVxuICAgKi9cbiAgcmVhZG9ubHkgY2FCdW5kbGVQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBIb3cgdG8gbG9jYXRlIHRoZSBidW5kbGVkIHNlbmRlciBlbnRyeSBwb2ludC5cbiAgICpcbiAgICogSW5qZWN0YWJsZSBzbyBhIHRlc3QgY2FuIGV4ZXJjaXNlIHRoZSBtaXNzaW5nLXNlbmRlciBwYXRoIHdpdGhvdXQgcmVhY2hpbmcgaW50byB0aGlzIG9iamVjdCdzXG4gICAqIHByaXZhdGVzOyByZXR1cm5pbmcgdW5kZWZpbmVkIGlzIHdoYXQgXCJub3Qgb24gZGlza1wiIGxvb2tzIGxpa2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbG9va2VkIHVwIHJlbGF0aXZlIHRvIHRoaXMgcGFja2FnZSdzIHJvb3RcbiAgICovXG4gIHJlYWRvbmx5IHJlc29sdmVTZW5kZXI/OiAoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQSB0ZWxlbWV0cnkgc2luayB0aGF0IGRlbGl2ZXJzIGV2ZW50cyBmcm9tIGEgZGV0YWNoZWQgY2hpbGQgcHJvY2Vzcy5cbiAqXG4gKiBFdmVudHMgYXJlIHdyaXR0ZW4gdG8gYSB0ZW1wb3JhcnkgZmlsZSBhbmQgaGFuZGVkIHRvIGEgY2hpbGQgdGhhdCBvdXRsaXZlcyB1cywgc28gdGhlIENMSSBjYW4gZXhpdFxuICogaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nIG9uIHRoZSBuZXR3b3JrLiBOb3RoaW5nIGhlcmUgZXZlciBsZWFybnMgd2hldGhlciBkZWxpdmVyeSBzdWNjZWVkZWQuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGRvZXMgbm90IGNoZWNrIGNvbm5lY3Rpdml0eSBmaXJzdDogdGhhdCBjaGVjayB3b3VsZCBpdHNlbGYgYmUgYSBuZXR3b3JrIGNhbGwgb24gdGhlXG4gKiBleGl0IHBhdGgsIHdoaWNoIGlzIHdoYXQgdGhpcyBzaW5rIGV4aXN0cyB0byBhdm9pZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFN1YnByb2Nlc3NUZWxlbWV0cnlTaW5rIGltcGxlbWVudHMgSVRlbGVtZXRyeVNpbmsge1xuICBwcml2YXRlIGV2ZW50czogVGVsZW1ldHJ5U2NoZW1hW10gPSBbXTtcbiAgcHJpdmF0ZSBlbmRwb2ludDogVVJMO1xuICBwcml2YXRlIGlvSGVscGVyOiBJb0hlbHBlcjtcbiAgcHJpdmF0ZSBzZW5kZXJQYXRoPzogc3RyaW5nO1xuICBwcml2YXRlIHByb3h5VXJsPzogc3RyaW5nO1xuICBwcml2YXRlIGNhQnVuZGxlUGF0aD86IHN0cmluZztcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IFN1YnByb2Nlc3NUZWxlbWV0cnlTaW5rUHJvcHMpIHtcbiAgICB0aGlzLmVuZHBvaW50ID0gbmV3IFVSTChwcm9wcy5lbmRwb2ludCk7XG5cbiAgICBpZiAoIXRoaXMuZW5kcG9pbnQuaG9zdG5hbWUgfHwgIXRoaXMuZW5kcG9pbnQucGF0aG5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ01hbGZvcm1lZEVuZHBvaW50JywgYFRlbGVtZXRyeSBFbmRwb2ludCBtYWxmb3JtZWQuIFJlY2VpdmVkIGhvc3RuYW1lOiAke3RoaXMuZW5kcG9pbnQuaG9zdG5hbWV9LCBwYXRobmFtZTogJHt0aGlzLmVuZHBvaW50LnBhdGhuYW1lfWApO1xuICAgIH1cblxuICAgIHRoaXMuaW9IZWxwZXIgPSBJb0hlbHBlci5mcm9tQWN0aW9uQXdhcmVJb0hvc3QocHJvcHMuaW9Ib3N0KTtcbiAgICB0aGlzLnNlbmRlclBhdGggPSAocHJvcHMucmVzb2x2ZVNlbmRlciA/PyByZXNvbHZlU2VuZGVyUGF0aCkoKTtcbiAgICB0aGlzLnByb3h5VXJsID0gcHJvcHMucHJveHlVcmw7XG4gICAgdGhpcy5jYUJ1bmRsZVBhdGggPSBwcm9wcy5jYUJ1bmRsZVBhdGg7XG5cbiAgICAvLyBCYXRjaCBldmVudHMgZXZlcnkgMzAgc2Vjb25kc1xuICAgIHNldEludGVydmFsKCgpID0+IHRoaXMuZmx1c2goKSwgMzAwMDApLnVucmVmKCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFuIGV2ZW50IHRvIHRoZSBjb2xsZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGVtaXQoZXZlbnQ6IFRlbGVtZXRyeVNjaGVtYSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZXZlbnRzLnB1c2goZXZlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmQgd2hhdGV2ZXIgaGFzIGFjY3VtdWxhdGVkIHRvIGEgZGV0YWNoZWQgc2VuZGVyLlxuICAgKlxuICAgKiBDbGVhcnMgdGhlIGJhdGNoIGVpdGhlciB3YXk6IGRlbGl2ZXJ5IGlzIG9uZS1zaG90LCB0aGUgcHJvY2VzcyB0aGF0IHdvdWxkIHJldHJ5IGhhcyB1c3VhbGx5XG4gICAqIGV4aXRlZCwgYW5kIHJldGFpbmluZyB0aGUgZXZlbnRzIHdvdWxkIGp1c3QgcmUtcmVwb3J0IHRoZSBmYWlsdXJlIGFuZCByZWdyb3cgdGhlIGJhdGNoIGV2ZXJ5IDMwcy5cbiAgICogVGhpcyBpcyB0aGUgc2luZ2xlIHBsYWNlIGRlbGl2ZXJ5IGZhaWx1cmVzIGFyZSBoYW5kbGVkOyBgZGlzcGF0Y2hgIHJlcG9ydHMgdGhlbSBieSB0aHJvd2luZy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBmbHVzaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5ldmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYmF0Y2ggPSB0aGlzLmV2ZW50cztcbiAgICB0aGlzLmV2ZW50cyA9IFtdO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2godGhpcy5lbmRwb2ludCwgeyBldmVudHM6IGJhdGNoIH0pO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgLy8gQm90aCBoYW5kLW9mZiBmYWlsdXJlcyBhcnJpdmUgaGVyZTogbm8gc2VuZGVyIG9uIGRpc2ssIGFuZCBhIHBheWxvYWQgd3JpdGUgb3Igc3Bhd24gdGhhdFxuICAgICAgLy8gdGhyb3dzLiBOb3RoaW5nIHJldHJpZXMgYW5kIG5vIGZhbGxiYWNrIHJ1bnMsIHNvIHJlcG9ydCBob3cgbXVjaCB3YXMgbG9zdCwgbm90IG9ubHkgd2h5LlxuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5kZWZhdWx0cy50cmFjZShgRmFpbGVkIHRvIHNlbmQgdGVsZW1ldHJ5IGV2ZW50OiAke2UubWVzc2FnZX0uIERyb3BwZWQgJHtiYXRjaC5sZW5ndGh9IGV2ZW50KHMpLmApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kIHRoZSBiYXRjaCB0byBhIGRldGFjaGVkIHNlbmRlciBwcm9jZXNzLlxuICAgKlxuICAgKiBUaHJvd3MgaWYgdGhlIGJhdGNoIGNvdWxkIG5vdCBiZSBoYW5kZWQgb3Zlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGlzcGF0Y2godXJsOiBVUkwsIGJvZHk6IFRlbGVtZXRyeUJhdGNoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnNlbmRlclBhdGgpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1NlbmRlck5vdEZvdW5kJywgYFVuYWJsZSB0byBsb2NhdGUgdGhlIHRlbGVtZXRyeSBzZW5kZXIgYXQgJHtTRU5ERVJfRU5UUllfUE9JTlR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnOiBUZWxlbWV0cnlTZW5kZXJDb25maWcgPSB7XG4gICAgICBlbmRwb2ludDogdXJsLmhyZWYsXG4gICAgICBib2R5LFxuICAgICAgcHJveHlVcmw6IHRoaXMucHJveHlVcmwsXG4gICAgICBjYUJ1bmRsZVBhdGg6IHRoaXMuY2FCdW5kbGVQYXRoLFxuICAgIH07XG4gICAgY29uc3QgcGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KGNvbmZpZyk7XG5cbiAgICAvLyBBIGZpbGUgcmF0aGVyIHRoYW4gdGhlIGNoaWxkJ3Mgc3RkaW46IHdyaXRpbmcgdG8gc3RkaW4gYmxvY2tzIHRoZSBwYXJlbnQgb25jZSB0aGUgcGF5bG9hZFxuICAgIC8vIG91dGdyb3dzIHRoZSBPUyBwaXBlIGJ1ZmZlciwgd2hpY2ggaXMgdGhlIHdhaXQgdGhpcyBzaW5rIGV4aXN0cyB0byBhdm9pZC5cbiAgICBjb25zdCBwYXlsb2FkUGF0aCA9IHBhdGguam9pbihvcy50bXBkaXIoKSwgYGNkay10ZWxlbWV0cnktJHtwcm9jZXNzLnBpZH0tJHtyYW5kb21VVUlEKCl9Lmpzb25gKTtcblxuICAgIHRyeSB7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKHBheWxvYWRQYXRoLCBwYXlsb2FkLCB7IGVuY29kaW5nOiAndXRmLTgnLCBtb2RlOiAwbzYwMCB9KTtcblxuICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bihwcm9jZXNzLmV4ZWNQYXRoLCBbdGhpcy5zZW5kZXJQYXRoLCBwYXlsb2FkUGF0aF0sIHtcbiAgICAgICAgZGV0YWNoZWQ6IHRydWUsXG4gICAgICAgIC8vIFBhc3MgdGhlIGNoaWxkJ3MgZGlhZ25vc3RpY3MgdGhyb3VnaCBvbmx5IHdoZW4gYXNrZWQ7IG90aGVyd2lzZSBub3RoaW5nIHJlYWRzIHRoZW0uXG4gICAgICAgIHN0ZGlvOiBzZW5kZXJEZWJ1Z0VuYWJsZWQoKSA/IFsnaWdub3JlJywgJ2lnbm9yZScsICdpbmhlcml0J10gOiAnaWdub3JlJyxcbiAgICAgICAgd2luZG93c0hpZGU6IHRydWUsXG4gICAgICAgIHNoZWxsOiBmYWxzZSxcbiAgICAgICAgLy8gRG8gbm90IGhvbGQgYSByZWZlcmVuY2UgdG8gdGhlIHVzZXIncyB3b3JraW5nIGRpcmVjdG9yeTsgdGhleSBtYXkgd2FudCB0byBkZWxldGUgaXQuXG4gICAgICAgIGN3ZDogb3MudG1wZGlyKCksXG4gICAgICB9KTtcblxuICAgICAgLy8gRmlyZXMgYWZ0ZXIgdGhlIENMSSBtYXkgYWxyZWFkeSBoYXZlIGV4aXRlZCwgc28gaXQgY2Fubm90IGdvIHRocm91Z2ggdGhlIElvSG9zdC4gU3RpbGwgdGhlXG4gICAgICAvLyBvbmx5IG5vdGlmaWNhdGlvbiBmb3IgYSBzcGF3biB0aGF0IGlzIHJlZnVzZWQgYWZ0ZXIgdGhpcyBtZXRob2QgcmV0dXJucy5cbiAgICAgIGNoaWxkLm9uKCdlcnJvcicsIChlOiBFcnJvcikgPT4ge1xuICAgICAgICBkZWJ1Z1RyYWNlKGBmYWlsZWQgdG8gc3Bhd24gc2VuZGVyOiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgdHJ5VW5saW5rKHBheWxvYWRQYXRoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBOb2RlIHJlcG9ydHMgYSByZWZ1c2VkIHNwYXduIChFTk9FTlQsIEVBQ0NFUywgRU1GSUxFKSBvbiB0aGF0IGBlcnJvcmAgZXZlbnQsIHdoaWNoIGZpcmVzXG4gICAgICAvLyBhZnRlciB0aGlzIG1ldGhvZCBoYXMgYWxyZWFkeSByZXR1cm5lZCAtLSBpdCBkb2VzIE5PVCB0aHJvdyBoZXJlLiBsaWJ1diBkb2VzIGxlYXZlIGBwaWRgXG4gICAgICAvLyB1bnNldCBzeW5jaHJvbm91c2x5IHRob3VnaCwgc28gdGhpcyBpcyB0aGUgb25lIHBvaW50IHdoZXJlIHRoZSBmYWlsdXJlIGNhbiBzdGlsbCBiZSByZXBvcnRlZFxuICAgICAgLy8gYXMgb25lLiBXaXRob3V0IGl0IHRoZSBiYXRjaCBpcyBjb3VudGVkIGFzIGhhbmRlZCBvZmYgYW5kIHRyYWNlZCB3aXRoIGBwaWQgdW5kZWZpbmVkYC5cbiAgICAgIGlmIChjaGlsZC5waWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdTcGF3blJlZnVzZWQnLCAndGhlIHNlbmRlciBwcm9jZXNzIHdhcyBuZXZlciBjcmVhdGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGNoaWxkLnVucmVmKCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIuZGVmYXVsdHMudHJhY2UoYCR7RElTUEFUQ0hFRF9UUkFDRX0gKHBpZCAke2NoaWxkLnBpZH0sICR7QnVmZmVyLmJ5dGVMZW5ndGgocGF5bG9hZCl9IGJ5dGVzKWApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdHJ5VW5saW5rKHBheWxvYWRQYXRoKTtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0Rpc3BhdGNoRmFpbGVkJywgYFNwYXduaW5nIGEgc2VuZGVyIGZvciBQT1NUICR7dXJsLmhvc3RuYW1lfSR7dXJsLnBhdGhuYW1lfSBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIExvY2F0ZSB0aGUgYnVuZGxlZCBzZW5kZXIgZW50cnkgcG9pbnQgaW5zaWRlIHRoaXMgcGFja2FnZS5cbiAqXG4gKiBXYWxrcyB1cCB0byB0aGUgcGFja2FnZSByb290LCB3aGljaCB3b3JrcyBib3RoIGZyb20gYGxpYi9gIGluIHNvdXJjZSBhbmQgZnJvbSB0aGUgcmVsZWFzZWQgYnVuZGxlLlxuICogYHByb2Nlc3MuYXJndlsxXWAgaXMgZGVsaWJlcmF0ZWx5IE5PVCB1c2VkOiBpdCBtYXkgYmUgdGhlIGAuYmluL2Nka2Agc3ltbGluaywgdGhlIGBjZGtgIGFsaWFzXG4gKiBwYWNrYWdlJ3Mgd3JhcHBlciwgb3IgLS0gd2hlbiB0aGUgQ0xJIGlzIGRyaXZlbiBwcm9ncmFtbWF0aWNhbGx5IC0tIHNvbWVib2R5IGVsc2UncyBzY3JpcHQuXG4gKlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIGVudHJ5IHBvaW50IGlzIG5vdCBvbiBkaXNrLCBpbiB3aGljaCBjYXNlIHRlbGVtZXRyeSBpcyBza2lwcGVkLlxuICovXG5mdW5jdGlvbiByZXNvbHZlU2VuZGVyUGF0aCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCByb290ID0gY2xpUm9vdERpcihmYWxzZSk7XG4gIGlmICghcm9vdCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBzZW5kZXJQYXRoID0gcGF0aC5qb2luKHJvb3QsIFNFTkRFUl9FTlRSWV9QT0lOVCk7XG4gIHJldHVybiBmcy5leGlzdHNTeW5jKHNlbmRlclBhdGgpID8gc2VuZGVyUGF0aCA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gdHJ5VW5saW5rKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBmcy51bmxpbmtTeW5jKGZpbGVQYXRoKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gTm90aGluZyB1c2VmdWwgdG8gZG8gYWJvdXQgaXQ7IHRoZSBPUyBjbGVhbnMgaXRzIG93biB0ZW1wIGRpcmVjdG9yeS5cbiAgfVxufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIHVzZXIgYXNrZWQgdG8gc2VlIHRoZSBzZW5kZXIncyBkaWFnbm9zdGljcy5cbiAqL1xuZnVuY3Rpb24gc2VuZGVyRGVidWdFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuQ0RLX1RFTEVNRVRSWV9TRU5ERVJfREVCVUcgPT09ICcxJztcbn1cblxuLyoqXG4gKiBEaWFnbm9zdGljcyBmb3IgZmFpbHVyZXMgdGhhdCBzdXJmYWNlIGFmdGVyIHRoZSBDTEkgbWF5IGFscmVhZHkgaGF2ZSBleGl0ZWQsIHNvIHRoZXkgY2Fubm90IGdvXG4gKiB0aHJvdWdoIHRoZSBJb0hvc3QuIEdhdGVkIGJlaGluZCB0aGUgc2FtZSB2YXJpYWJsZSBhcyB0aGUgc2VuZGVyJ3Mgb3duIHRyYWNlcy5cbiAqL1xuZnVuY3Rpb24gZGVidWdUcmFjZShtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFzZW5kZXJEZWJ1Z0VuYWJsZWQoKSkge1xuICAgIHJldHVybjtcbiAgfVxuICB0cnkge1xuICAgIGZzLndyaXRlU3luYygyLCBgW2Nkay10ZWxlbWV0cnktZGlzcGF0Y2hdICR7bWVzc2FnZX1cXG5gKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gRGlhZ25vc3RpY3MgbXVzdCBuZXZlciBiZSB0aGUgcmVhc29uIGFueXRoaW5nIGZhaWxzLlxuICB9XG59XG4iXX0=