testcafe
Version:
Automated browser testing for the modern web development stack.
145 lines • 19.4 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const debug_1 = __importDefault(require("debug"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const promisified_functions_1 = require("../../promisified-functions");
const commands_1 = __importDefault(require("./commands"));
const WORKER_PATH = require.resolve('./worker');
const WORKER_STDIO_CONFIG = ['ignore', 'pipe', 'pipe', 'ipc'];
const DEBUG_LOGGER = (0, debug_1.default)('testcafe:utils:temp-directory:cleanup-process');
class CleanupProcess {
constructor() {
this.worker = null;
this.initialized = false;
this.initPromise = Promise.resolve(void 0);
this.errorPromise = null;
this.messageCounter = 0;
this.pendingResponses = {};
}
_sendMessage(id, msg) {
return Promise.race([
(0, promisified_functions_1.sendMessageToChildProcess)(this.worker, Object.assign({ id }, msg)),
this._waitProcessError(),
]);
}
_onResponse(response) {
const pendingResponse = this.pendingResponses[response.id];
if (response.error) {
if (pendingResponse)
pendingResponse.control.reject(response.error);
else
this.pendingResponses[response.id] = Promise.reject(response.error);
}
else if (pendingResponse)
pendingResponse.control.resolve();
else
this.pendingResponses[response.id] = Promise.resolve();
}
async _waitResponse(id) {
if (!this.pendingResponses[id]) {
const promiseControl = {};
this.pendingResponses[id] = new Promise((resolve, reject) => {
Object.assign(promiseControl, { resolve, reject });
});
this.pendingResponses[id].control = promiseControl;
}
try {
await this.pendingResponses[id];
}
finally {
delete this.pendingResponses[id];
}
}
async _waitResponseForMessage(msg) {
const currentId = this.messageCounter;
this.messageCounter++;
await this._sendMessage(currentId, msg);
await this._waitResponse(currentId);
}
_waitProcessExit() {
return (0, promisify_event_1.default)(this.worker, 'exit')
.then(exitCode => Promise.reject(new Error(`Worker process terminated with code ${exitCode}`)));
}
_waitProcessError() {
if (this.errorPromise)
return this.errorPromise;
this.errorPromise = (0, promisify_event_1.default)(this.worker, 'error');
this.errorPromise.then(() => {
this.errorPromise = null;
});
return this.errorPromise;
}
_setupWorkerEventHandlers() {
this.worker.on('message', message => this._onResponse(message));
this.worker.stdout.on('data', data => DEBUG_LOGGER('Worker process stdout:\n', String(data)));
this.worker.stderr.on('data', data => DEBUG_LOGGER('Worker process stderr:\n', String(data)));
}
_unrefWorkerProcess() {
this.worker.unref();
this.worker.stdout.unref();
this.worker.stderr.unref();
const channel = this.worker.channel || this.worker._channel;
channel.unref();
}
_handleProcessError(error) {
this.initialized = false;
DEBUG_LOGGER(error);
}
init() {
this.initPromise = this.initPromise
.then(async (initialized) => {
if (initialized !== void 0)
return initialized;
this.worker = (0, child_process_1.spawn)(process.argv0, [WORKER_PATH], { detached: true, stdio: WORKER_STDIO_CONFIG });
this._setupWorkerEventHandlers();
this._unrefWorkerProcess();
const exitPromise = this._waitProcessExit();
try {
await Promise.race([
this._waitResponseForMessage({ command: commands_1.default.init }),
this._waitProcessError(),
exitPromise,
]);
this.initialized = true;
exitPromise.catch(error => this._handleProcessError(error));
this.worker.on('error', error => this._handleProcessError(error));
}
catch (e) {
DEBUG_LOGGER('Failed to start cleanup process');
DEBUG_LOGGER(e);
this.initialized = false;
}
return this.initialized;
});
return this.initPromise;
}
async addDirectory(path) {
if (!this.initialized)
return;
try {
await this._waitResponseForMessage({ command: commands_1.default.add, path });
}
catch (e) {
DEBUG_LOGGER(`Failed to add the ${path} directory to cleanup process`);
DEBUG_LOGGER(e);
}
}
async removeDirectory(path) {
if (!this.initialized)
return;
try {
await this._waitResponseForMessage({ command: commands_1.default.remove, path });
}
catch (e) {
DEBUG_LOGGER(`Failed to remove the ${path} directory in cleanup process`);
DEBUG_LOGGER(e);
}
}
}
exports.default = new CleanupProcess();
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvdGVtcC1kaXJlY3RvcnkvY2xlYW51cC1wcm9jZXNzL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQXNDO0FBQ3RDLGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsdUVBQXdFO0FBQ3hFLDBEQUFrQztBQUdsQyxNQUFNLFdBQVcsR0FBVyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3hELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUU5RCxNQUFNLFlBQVksR0FBRyxJQUFBLGVBQUssRUFBQywrQ0FBK0MsQ0FBQyxDQUFDO0FBRTVFLE1BQU0sY0FBYztJQUNoQjtRQUNJLElBQUksQ0FBQyxNQUFNLEdBQVMsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUksS0FBSyxDQUFDO1FBQzFCLElBQUksQ0FBQyxXQUFXLEdBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBRXpCLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELFlBQVksQ0FBRSxFQUFFLEVBQUUsR0FBRztRQUNqQixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDaEIsSUFBQSxpREFBeUIsRUFBQyxJQUFJLENBQUMsTUFBTSxrQkFBSSxFQUFFLElBQUssR0FBRyxFQUFHO1lBQ3RELElBQUksQ0FBQyxpQkFBaUIsRUFBRTtTQUMzQixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsV0FBVyxDQUFFLFFBQVE7UUFDakIsTUFBTSxlQUFlLEdBQUcsSUFB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cUJBQXFCLElBQUksK0JBQStCLENBQUMsQ0FBQztZQUN2RSxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDbkI7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGVBQWUsQ0FBRSxJQUFJO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVztZQUNqQixPQUFPO1FBRVgsSUFBSTtZQUNBLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLEVBQUUsT0FBTyxFQUFFLGtCQUFRLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7U0FDMUU7UUFDRCxPQUFPLENBQUMsRUFBRTtZQUNOLFlBQVksQ0FBQyx3QkFBd0IsSUFBSSwrQkFBK0IsQ0FBQyxDQUFDO1lBQzFFLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNuQjtJQUNMLENBQUM7Q0FDSjtBQUVELGtCQUFlLElBQUksY0FBYyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IHsgc2VuZE1lc3NhZ2VUb0NoaWxkUHJvY2VzcyB9IGZyb20gJy4uLy4uL3Byb21pc2lmaWVkLWZ1bmN0aW9ucyc7XG5pbXBvcnQgQ09NTUFORFMgZnJvbSAnLi9jb21tYW5kcyc7XG5cblxuY29uc3QgV09SS0VSX1BBVEggICAgICAgICA9IHJlcXVpcmUucmVzb2x2ZSgnLi93b3JrZXInKTtcbmNvbnN0IFdPUktFUl9TVERJT19DT05GSUcgPSBbJ2lnbm9yZScsICdwaXBlJywgJ3BpcGUnLCAnaXBjJ107XG5cbmNvbnN0IERFQlVHX0xPR0dFUiA9IGRlYnVnKCd0ZXN0Y2FmZTp1dGlsczp0ZW1wLWRpcmVjdG9yeTpjbGVhbnVwLXByb2Nlc3MnKTtcblxuY2xhc3MgQ2xlYW51cFByb2Nlc3Mge1xuICAgIGNvbnN0cnVjdG9yICgpIHtcbiAgICAgICAgdGhpcy53b3JrZXIgICAgICAgPSBudWxsO1xuICAgICAgICB0aGlzLmluaXRpYWxpemVkICA9IGZhbHNlO1xuICAgICAgICB0aGlzLmluaXRQcm9taXNlICA9IFByb21pc2UucmVzb2x2ZSh2b2lkIDApO1xuICAgICAgICB0aGlzLmVycm9yUHJvbWlzZSA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5tZXNzYWdlQ291bnRlciA9IDA7XG5cbiAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzID0ge307XG4gICAgfVxuXG4gICAgX3NlbmRNZXNzYWdlIChpZCwgbXNnKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgc2VuZE1lc3NhZ2VUb0NoaWxkUHJvY2Vzcyh0aGlzLndvcmtlciwgeyBpZCwgLi4ubXNnIH0pLFxuICAgICAgICAgICAgdGhpcy5fd2FpdFByb2Nlc3NFcnJvcigpLFxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICBfb25SZXNwb25zZSAocmVzcG9uc2UpIHtcbiAgICAgICAgY29uc3QgcGVuZGluZ1Jlc3BvbnNlID0gdGhpcy5wZW5kaW5nUmVzcG9uc2VzW3Jlc3BvbnNlLmlkXTtcblxuICAgICAgICBpZiAocmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgICAgICAgIGlmIChwZW5kaW5nUmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgcGVuZGluZ1Jlc3BvbnNlLmNvbnRyb2wucmVqZWN0KHJlc3BvbnNlLmVycm9yKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdSZXNwb25zZXNbcmVzcG9uc2UuaWRdID0gUHJvbWlzZS5yZWplY3QocmVzcG9uc2UuZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBlbmRpbmdSZXNwb25zZSlcbiAgICAgICAgICAgIHBlbmRpbmdSZXNwb25zZS5jb250cm9sLnJlc29sdmUoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW3Jlc3BvbnNlLmlkXSA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIGFzeW5jIF93YWl0UmVzcG9uc2UgKGlkKSB7XG4gICAgICAgIGlmICghdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXSkge1xuICAgICAgICAgICAgY29uc3QgcHJvbWlzZUNvbnRyb2wgPSB7fTtcblxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHByb21pc2VDb250cm9sLCB7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdSZXNwb25zZXNbaWRdLmNvbnRyb2wgPSBwcm9taXNlQ29udHJvbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBlbmRpbmdSZXNwb25zZXNbaWRdO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tpZF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBfd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSAobXNnKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRJZCA9IHRoaXMubWVzc2FnZUNvdW50ZXI7XG5cbiAgICAgICAgdGhpcy5tZXNzYWdlQ291bnRlcisrO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX3NlbmRNZXNzYWdlKGN1cnJlbnRJZCwgbXNnKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fd2FpdFJlc3BvbnNlKGN1cnJlbnRJZCk7XG4gICAgfVxuXG4gICAgX3dhaXRQcm9jZXNzRXhpdCAoKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNpZnlFdmVudCh0aGlzLndvcmtlciwgJ2V4aXQnKVxuICAgICAgICAgICAgLnRoZW4oZXhpdENvZGUgPT4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGBXb3JrZXIgcHJvY2VzcyB0ZXJtaW5hdGVkIHdpdGggY29kZSAke2V4aXRDb2RlfWApKSk7XG4gICAgfVxuXG4gICAgX3dhaXRQcm9jZXNzRXJyb3IgKCkge1xuICAgICAgICBpZiAodGhpcy5lcnJvclByb21pc2UpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcnJvclByb21pc2U7XG5cbiAgICAgICAgdGhpcy5lcnJvclByb21pc2UgPSBwcm9taXNpZnlFdmVudCh0aGlzLndvcmtlciwgJ2Vycm9yJyk7XG5cbiAgICAgICAgdGhpcy5lcnJvclByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVycm9yUHJvbWlzZSA9IG51bGw7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmVycm9yUHJvbWlzZTtcbiAgICB9XG5cbiAgICBfc2V0dXBXb3JrZXJFdmVudEhhbmRsZXJzICgpIHtcbiAgICAgICAgdGhpcy53b3JrZXIub24oJ21lc3NhZ2UnLCBtZXNzYWdlID0+IHRoaXMuX29uUmVzcG9uc2UobWVzc2FnZSkpO1xuXG4gICAgICAgIHRoaXMud29ya2VyLnN0ZG91dC5vbignZGF0YScsIGRhdGEgPT4gREVCVUdfTE9HR0VSKCdXb3JrZXIgcHJvY2VzcyBzdGRvdXQ6XFxuJywgU3RyaW5nKGRhdGEpKSk7XG4gICAgICAgIHRoaXMud29ya2VyLnN0ZGVyci5vbignZGF0YScsIGRhdGEgPT4gREVCVUdfTE9HR0VSKCdXb3JrZXIgcHJvY2VzcyBzdGRlcnI6XFxuJywgU3RyaW5nKGRhdGEpKSk7XG4gICAgfVxuXG4gICAgX3VucmVmV29ya2VyUHJvY2VzcyAoKSB7XG4gICAgICAgIHRoaXMud29ya2VyLnVucmVmKCk7XG4gICAgICAgIHRoaXMud29ya2VyLnN0ZG91dC51bnJlZigpO1xuICAgICAgICB0aGlzLndvcmtlci5zdGRlcnIudW5yZWYoKTtcblxuICAgICAgICBjb25zdCBjaGFubmVsID0gdGhpcy53b3JrZXIuY2hhbm5lbCB8fCB0aGlzLndvcmtlci5fY2hhbm5lbDtcblxuICAgICAgICBjaGFubmVsLnVucmVmKCk7XG4gICAgfVxuXG4gICAgX2hhbmRsZVByb2Nlc3NFcnJvciAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gICAgICAgIERFQlVHX0xPR0dFUihlcnJvcik7XG4gICAgfVxuXG4gICAgaW5pdCAoKSB7XG4gICAgICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXRQcm9taXNlXG4gICAgICAgICAgICAudGhlbihhc3luYyBpbml0aWFsaXplZCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxpemVkICE9PSB2b2lkIDApXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbml0aWFsaXplZDtcblxuICAgICAgICAgICAgICAgIHRoaXMud29ya2VyID0gc3Bhd24ocHJvY2Vzcy5hcmd2MCwgW1dPUktFUl9QQVRIXSwgeyBkZXRhY2hlZDogdHJ1ZSwgc3RkaW86IFdPUktFUl9TVERJT19DT05GSUcgfSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9zZXR1cFdvcmtlckV2ZW50SGFuZGxlcnMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl91bnJlZldvcmtlclByb2Nlc3MoKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXRQcm9taXNlID0gdGhpcy5fd2FpdFByb2Nlc3NFeGl0KCk7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSh7IGNvbW1hbmQ6IENPTU1BTkRTLmluaXQgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93YWl0UHJvY2Vzc0Vycm9yKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBleGl0UHJvbWlzZSxcbiAgICAgICAgICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgZXhpdFByb21pc2UuY2F0Y2goZXJyb3IgPT4gdGhpcy5faGFuZGxlUHJvY2Vzc0Vycm9yKGVycm9yKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JrZXIub24oJ2Vycm9yJywgZXJyb3IgPT4gdGhpcy5faGFuZGxlUHJvY2Vzc0Vycm9yKGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIERFQlVHX0xPR0dFUignRmFpbGVkIHRvIHN0YXJ0IGNsZWFudXAgcHJvY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICBERUJVR19MT0dHRVIoZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXRpYWxpemVkO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5pdFByb21pc2U7XG4gICAgfVxuXG4gICAgYXN5bmMgYWRkRGlyZWN0b3J5IChwYXRoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbml0aWFsaXplZClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSh7IGNvbW1hbmQ6IENPTU1BTkRTLmFkZCwgcGF0aCB9KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgREVCVUdfTE9HR0VSKGBGYWlsZWQgdG8gYWRkIHRoZSAke3BhdGh9IGRpcmVjdG9yeSB0byBjbGVhbnVwIHByb2Nlc3NgKTtcbiAgICAgICAgICAgIERFQlVHX0xPR0dFUihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHJlbW92ZURpcmVjdG9yeSAocGF0aCkge1xuICAgICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX3dhaXRSZXNwb25zZUZvck1lc3NhZ2UoeyBjb21tYW5kOiBDT01NQU5EUy5yZW1vdmUsIHBhdGggfSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIERFQlVHX0xPR0dFUihgRmFpbGVkIHRvIHJlbW92ZSB0aGUgJHtwYXRofSBkaXJlY3RvcnkgaW4gY2xlYW51cCBwcm9jZXNzYCk7XG4gICAgICAgICAgICBERUJVR19MT0dHRVIoZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG5ldyBDbGVhbnVwUHJvY2VzcygpO1xuIl19