@adobe/ccweb-add-on-devcert
Version:
Generate trusted local SSL/TLS certificates for local SSL development
136 lines • 20.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.certificateExpiryInDays = exports.caExpiryInDays = exports.removeAll = exports.removeDomain = exports.location = exports.configuredDomains = exports.hasCertificateFor = exports.certificateFor = void 0;
const tslib_1 = require("tslib");
const command_exists_1 = require("command-exists");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_1 = require("fs");
const is_valid_domain_1 = tslib_1.__importDefault(require("is-valid-domain"));
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const certificate_authority_1 = tslib_1.__importStar(require("./certificate-authority"));
const certificates_1 = require("./certificates");
const constants_1 = require("./constants");
const platforms_1 = tslib_1.__importDefault(require("./platforms"));
const user_interface_1 = tslib_1.__importDefault(require("./user-interface"));
const utils_1 = require("./utils");
const debug = debug_1.default("devcert");
/**
* Request an SSL certificate for the given app name signed by the devcert root
* certificate authority. If devcert has previously generated a certificate for
* that app name on this machine, it will reuse that certificate.
*
* If this is the first time devcert is being run on this machine, it will
* generate and attempt to install a root certificate authority.
*
* Returns a promise that resolves with { key, cert }, where `key` and `cert`
* are Buffers with the contents of the certificate private key and certificate
* file, respectively
*
* If `options.getCaBuffer` is true, return value will include the ca certificate data
* as { ca: Buffer }
*
* If `options.getCaPath` is true, return value will include the ca certificate path
* as { caPath: string }
*/
function certificateFor(requestedDomains, options = {}) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains];
domains.forEach((domain) => {
if (domain !== "localhost" &&
!is_valid_domain_1.default(domain, { subdomain: true, wildcard: false, allowUnicode: true, topLevel: false })) {
throw new Error(`"${domain}" is not a valid domain name.`);
}
});
const domainPath = constants_1.getStableDomainPath(domains);
debug(`Certificate requested for ${domains}. Skipping certutil install: ${Boolean(options.skipCertutilInstall)}. Skipping hosts file: ${Boolean(options.skipHostsFile)}`);
if (options.ui) {
Object.assign(user_interface_1.default, options.ui);
}
if (!constants_1.isMac && !constants_1.isLinux && !constants_1.isWindows) {
throw new Error(`Platform not supported: "${process.platform}"`);
}
if (!command_exists_1.sync("openssl")) {
throw new Error("OpenSSL not found: OpenSSL is required to generate SSL certificates - make sure it is installed and available in your PATH");
}
let domainKeyPath = constants_1.pathForDomain(domainPath, `private-key.key`);
let domainCertPath = constants_1.pathForDomain(domainPath, `certificate.crt`);
if (!fs_1.existsSync(constants_1.rootCAKeyPath)) {
debug("Root CA is not installed yet, so it must be our first run. Installing root CA ...");
yield certificate_authority_1.default(options);
}
else if (options.getCaBuffer || options.getCaPath) {
debug("Root CA is not readable, but it probably is because an earlier version of devcert locked it. Trying to fix...");
yield certificate_authority_1.ensureCACertReadable(options);
}
if (!fs_1.existsSync(constants_1.pathForDomain(domainPath, `certificate.crt`))) {
debug(`Can't find certificate file for ${domains}, so it must be the first request for ${domains}. Generating and caching ...`);
yield certificates_1.generateDomainCertificate(domains);
}
if (!options.skipHostsFile) {
domains.forEach((domain) => tslib_1.__awaiter(this, void 0, void 0, function* () {
yield platforms_1.default.addDomainToHostFileIfMissing(domain);
}));
}
debug(`Returning domain certificate`);
const ret = {
key: fs_1.readFileSync(domainKeyPath),
cert: fs_1.readFileSync(domainCertPath),
};
if (options.getCaBuffer)
ret.ca = fs_1.readFileSync(constants_1.rootCACertPath);
if (options.getCaPath)
ret.caPath = constants_1.rootCACertPath;
return ret;
});
}
exports.certificateFor = certificateFor;
function hasCertificateFor(requestedDomains) {
const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains];
const domainPath = constants_1.getStableDomainPath(domains);
return fs_1.existsSync(constants_1.pathForDomain(domainPath, `certificate.crt`));
}
exports.hasCertificateFor = hasCertificateFor;
function configuredDomains() {
return fs_1.readdirSync(constants_1.domainsDir);
}
exports.configuredDomains = configuredDomains;
function location() {
return constants_1.configDir;
}
exports.location = location;
function removeDomain(requestedDomains) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains];
yield certificates_1.revokeDomainCertificate(domains);
const domainPath = constants_1.getStableDomainPath(domains);
return rimraf_1.default.sync(constants_1.pathForDomain(domainPath));
});
}
exports.removeDomain = removeDomain;
function removeAll() {
certificate_authority_1.uninstall();
}
exports.removeAll = removeAll;
function caExpiryInDays() {
try {
const caExpiryData = utils_1.openssl(['x509', '-in', constants_1.rootCACertPath, '-noout', '-enddate']).toString().trim();
return utils_1.parseOpenSSLExpiryData(caExpiryData);
}
catch (_a) {
return -1;
}
}
exports.caExpiryInDays = caExpiryInDays;
function certificateExpiryInDays(domain) {
const domainPath = constants_1.getStableDomainPath([domain]);
let domainCertPath = constants_1.pathForDomain(domainPath, 'certificate.crt');
try {
const certExpiryData = utils_1.openssl(['x509', '-in', domainCertPath, '-noout', '-enddate']).toString().trim();
return utils_1.parseOpenSSLExpiryData(certExpiryData);
}
catch (_a) {
return -1;
}
}
exports.certificateExpiryInDays = certificateExpiryInDays;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbImluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxtREFBdUQ7QUFDdkQsMERBQWdDO0FBQ2hDLDJCQUE0RjtBQUM1Riw4RUFBNEM7QUFDNUMsNERBQTRCO0FBQzVCLHlGQUF1RztBQUN2RyxpREFBb0Y7QUFDcEYsMkNBVXFCO0FBQ3JCLG9FQUEwQztBQUMxQyw4RUFBcUQ7QUFDckQsbUNBQTBEO0FBRTFELE1BQU0sS0FBSyxHQUFHLGVBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQTZCckM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsU0FBc0IsY0FBYyxDQUNoQyxnQkFBbUMsRUFDbkMsVUFBYSxFQUFPOztRQUVwQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDeEYsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3ZCLElBQ0ksTUFBTSxLQUFLLFdBQVc7Z0JBQ3RCLENBQUMseUJBQWEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFDbkc7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLE1BQU0sK0JBQStCLENBQUMsQ0FBQzthQUM5RDtRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxVQUFVLEdBQUcsK0JBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEQsS0FBSyxDQUNELDZCQUE2QixPQUFPLGdDQUFnQyxPQUFPLENBQ3ZFLE9BQU8sQ0FBQyxtQkFBbUIsQ0FDOUIsMEJBQTBCLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFB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QkFBc0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztLQUNqRDtJQUFDLFdBQU07UUFDSixPQUFPLENBQUMsQ0FBQyxDQUFDO0tBQ2I7QUFDTCxDQUFDO0FBVkQsMERBVUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzeW5jIGFzIGNvbW1hbmRFeGlzdHMgfSBmcm9tIFwiY29tbWFuZC1leGlzdHNcIjtcbmltcG9ydCBjcmVhdGVEZWJ1ZyBmcm9tIFwiZGVidWdcIjtcbmltcG9ydCB7IGV4aXN0c1N5bmMgYXMgZXhpc3RzLCByZWFkRmlsZVN5bmMgYXMgcmVhZEZpbGUsIHJlYWRkaXJTeW5jIGFzIHJlYWRkaXIgfSBmcm9tIFwiZnNcIjtcbmltcG9ydCBpc1ZhbGlkRG9tYWluIGZyb20gXCJpcy12YWxpZC1kb21haW5cIjtcbmltcG9ydCByaW1yYWYgZnJvbSBcInJpbXJhZlwiO1xuaW1wb3J0IGluc3RhbGxDZXJ0aWZpY2F0ZUF1dGhvcml0eSwgeyBlbnN1cmVDQUNlcnRSZWFkYWJsZSwgdW5pbnN0YWxsIH0gZnJvbSBcIi4vY2VydGlmaWNhdGUtYXV0aG9yaXR5XCI7XG5pbXBvcnQgeyBnZW5lcmF0ZURvbWFpbkNlcnRpZmljYXRlLCByZXZva2VEb21haW5DZXJ0aWZpY2F0ZSB9IGZyb20gXCIuL2NlcnRpZmljYXRlc1wiO1xuaW1wb3J0IHtcbiAgICBjb25maWdEaXIsXG4gICAgZG9tYWluc0RpcixcbiAgICBnZXRTdGFibGVEb21haW5QYXRoLFxuICAgIGlzTGludXgsXG4gICAgaXNNYWMsXG4gICAgaXNXaW5kb3dzLFxuICAgIHBhdGhGb3JEb21haW4sXG4gICAgcm9vdENBQ2VydFBhdGgsXG4gICAgcm9vdENBS2V5UGF0aCxcbn0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgY3VycmVudFBsYXRmb3JtIGZyb20gXCIuL3BsYXRmb3Jtc1wiO1xuaW1wb3J0IFVJLCB7IFVzZXJJbnRlcmZhY2UgfSBmcm9tIFwiLi91c2VyLWludGVyZmFjZVwiO1xuaW1wb3J0IHsgb3BlbnNzbCwgcGFyc2VPcGVuU1NMRXhwaXJ5RGF0YSB9IGZyb20gJy4vdXRpbHMnO1xuXG5jb25zdCBkZWJ1ZyA9IGNyZWF0ZURlYnVnKFwiZGV2Y2VydFwiKTtcblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zIC8qIGV4dGVuZHMgUGFydGlhbDxJQ2FCdWZmZXJPcHRzICYgSUNhUGF0aE9wdHM+ICAqLyB7XG4gICAgLyoqIFJldHVybiB0aGUgQ0EgY2VydGlmaWNhdGUgZGF0YT8gKi9cbiAgICBnZXRDYUJ1ZmZlcj86IGJvb2xlYW47XG4gICAgLyoqIFJldHVybiB0aGUgcGF0aCB0byB0aGUgQ0EgY2VydGlmaWNhdGU/ICovXG4gICAgZ2V0Q2FQYXRoPzogYm9vbGVhbjtcbiAgICAvKiogSWYgYGNlcnR1dGlsYCBpcyBub3QgaW5zdGFsbGVkIGFscmVhZHkgKGZvciB1cGRhdGluZyBuc3MgZGF0YWJhc2VzOyBlLmcuIGZpcmVmb3gpLCBkbyBub3QgYXR0ZW1wdCB0byBpbnN0YWxsIGl0ICovXG4gICAgc2tpcENlcnR1dGlsSW5zdGFsbD86IGJvb2xlYW47XG4gICAgLyoqIERvIG5vdCB1cGRhdGUgeW91ciBzeXN0ZW1zIGhvc3QgZmlsZSB3aXRoIHRoZSBkb21haW4gbmFtZSBvZiB0aGUgY2VydGlmaWNhdGUgKi9cbiAgICBza2lwSG9zdHNGaWxlPzogYm9vbGVhbjtcbiAgICAvKiogVXNlciBpbnRlcmZhY2UgaG9va3MgKi9cbiAgICB1aT86IFVzZXJJbnRlcmZhY2U7XG59XG5cbmludGVyZmFjZSBJQ2FCdWZmZXIge1xuICAgIGNhOiBCdWZmZXI7XG59XG5pbnRlcmZhY2UgSUNhUGF0aCB7XG4gICAgY2FQYXRoOiBzdHJpbmc7XG59XG5pbnRlcmZhY2UgSURvbWFpbkRhdGEge1xuICAgIGtleTogQnVmZmVyO1xuICAgIGNlcnQ6IEJ1ZmZlcjtcbn1cbnR5cGUgSVJldHVybkNhPE8gZXh0ZW5kcyBPcHRpb25zPiA9IE9bXCJnZXRDYUJ1ZmZlclwiXSBleHRlbmRzIHRydWUgPyBJQ2FCdWZmZXIgOiBmYWxzZTtcbnR5cGUgSVJldHVybkNhUGF0aDxPIGV4dGVuZHMgT3B0aW9ucz4gPSBPW1wiZ2V0Q2FQYXRoXCJdIGV4dGVuZHMgdHJ1ZSA/IElDYVBhdGggOiBmYWxzZTtcbnR5cGUgSVJldHVybkRhdGE8TyBleHRlbmRzIE9wdGlvbnMgPSB7fT4gPSBJRG9tYWluRGF0YSAmIElSZXR1cm5DYTxPPiAmIElSZXR1cm5DYVBhdGg8Tz47XG5cbi8qKlxuICogUmVxdWVzdCBhbiBTU0wgY2VydGlmaWNhdGUgZm9yIHRoZSBnaXZlbiBhcHAgbmFtZSBzaWduZWQgYnkgdGhlIGRldmNlcnQgcm9vdFxuICogY2VydGlmaWNhdGUgYXV0aG9yaXR5LiBJZiBkZXZjZXJ0IGhhcyBwcmV2aW91c2x5IGdlbmVyYXRlZCBhIGNlcnRpZmljYXRlIGZvclxuICogdGhhdCBhcHAgbmFtZSBvbiB0aGlzIG1hY2hpbmUsIGl0IHdpbGwgcmV1c2UgdGhhdCBjZXJ0aWZpY2F0ZS5cbiAqXG4gKiBJZiB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lIGRldmNlcnQgaXMgYmVpbmcgcnVuIG9uIHRoaXMgbWFjaGluZSwgaXQgd2lsbFxuICogZ2VuZXJhdGUgYW5kIGF0dGVtcHQgdG8gaW5zdGFsbCBhIHJvb3QgY2VydGlmaWNhdGUgYXV0aG9yaXR5LlxuICpcbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB7IGtleSwgY2VydCB9LCB3aGVyZSBga2V5YCBhbmQgYGNlcnRgXG4gKiBhcmUgQnVmZmVycyB3aXRoIHRoZSBjb250ZW50cyBvZiB0aGUgY2VydGlmaWNhdGUgcHJpdmF0ZSBrZXkgYW5kIGNlcnRpZmljYXRlXG4gKiBmaWxlLCByZXNwZWN0aXZlbHlcbiAqXG4gKiBJZiBgb3B0aW9ucy5nZXRDYUJ1ZmZlcmAgaXMgdHJ1ZSwgcmV0dXJuIHZhbHVlIHdpbGwgaW5jbHVkZSB0aGUgY2EgY2VydGlmaWNhdGUgZGF0YVxuICogYXMgeyBjYTogQnVmZmVyIH1cbiAqXG4gKiBJZiBgb3B0aW9ucy5nZXRDYVBhdGhgIGlzIHRydWUsIHJldHVybiB2YWx1ZSB3aWxsIGluY2x1ZGUgdGhlIGNhIGNlcnRpZmljYXRlIHBhdGhcbiAqIGFzIHsgY2FQYXRoOiBzdHJpbmcgfVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2VydGlmaWNhdGVGb3I8TyBleHRlbmRzIE9wdGlvbnM+KFxuICAgIHJlcXVlc3RlZERvbWFpbnM6IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM6IE8gPSB7fSBhcyBPXG4pOiBQcm9taXNlPElSZXR1cm5EYXRhPE8+PiB7XG4gICAgY29uc3QgZG9tYWlucyA9IEFycmF5LmlzQXJyYXkocmVxdWVzdGVkRG9tYWlucykgPyByZXF1ZXN0ZWREb21haW5zIDogW3JlcXVlc3RlZERvbWFpbnNdO1xuICAgIGRvbWFpbnMuZm9yRWFjaCgoZG9tYWluKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGRvbWFpbiAhPT0gXCJsb2NhbGhvc3RcIiAmJlxuICAgICAgICAgICAgIWlzVmFsaWREb21haW4oZG9tYWluLCB7IHN1YmRvbWFpbjogdHJ1ZSwgd2lsZGNhcmQ6IGZhbHNlLCBhbGxvd1VuaWNvZGU6IHRydWUsIHRvcExldmVsOiBmYWxzZSB9KVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgXCIke2RvbWFpbn1cIiBpcyBub3QgYSB2YWxpZCBkb21haW4gbmFtZS5gKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoZG9tYWlucyk7XG4gICAgZGVidWcoXG4gICAgICAgIGBDZXJ0aWZpY2F0ZSByZXF1ZXN0ZWQgZm9yICR7ZG9tYWluc30uIFNraXBwaW5nIGNlcnR1dGlsIGluc3RhbGw6ICR7Qm9vbGVhbihcbiAgICAgICAgICAgIG9wdGlvbnMuc2tpcENlcnR1dGlsSW5zdGFsbFxuICAgICAgICApfS4gU2tpcHBpbmcgaG9zdHMgZmlsZTogJHtCb29sZWFuKG9wdGlvbnMuc2tpcEhvc3RzRmlsZSl9YFxuICAgICk7XG5cbiAgICBpZiAob3B0aW9ucy51aSkge1xuICAgICAgICBPYmplY3QuYXNzaWduKFVJLCBvcHRpb25zLnVpKTtcbiAgICB9XG5cbiAgICBpZiAoIWlzTWFjICYmICFpc0xpbnV4ICYmICFpc1dpbmRvd3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQbGF0Zm9ybSBub3Qgc3VwcG9ydGVkOiBcIiR7cHJvY2Vzcy5wbGF0Zm9ybX1cImApO1xuICAgIH1cblxuICAgIGlmICghY29tbWFuZEV4aXN0cyhcIm9wZW5zc2xcIikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgXCJPcGVuU1NMIG5vdCBmb3VuZDogT3BlblNTTCBpcyByZXF1aXJlZCB0byBnZW5lcmF0ZSBTU0wgY2VydGlmaWNhdGVzIC0gbWFrZSBzdXJlIGl0IGlzIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIGluIHlvdXIgUEFUSFwiXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IGRvbWFpbktleVBhdGggPSBwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBwcml2YXRlLWtleS5rZXlgKTtcbiAgICBsZXQgZG9tYWluQ2VydFBhdGggPSBwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBjZXJ0aWZpY2F0ZS5jcnRgKTtcblxuICAgIGlmICghZXhpc3RzKHJvb3RDQUtleVBhdGgpKSB7XG4gICAgICAgIGRlYnVnKFwiUm9vdCBDQSBpcyBub3QgaW5zdGFsbGVkIHlldCwgc28gaXQgbXVzdCBiZSBvdXIgZmlyc3QgcnVuLiBJbnN0YWxsaW5nIHJvb3QgQ0EgLi4uXCIpO1xuICAgICAgICBhd2FpdCBpbnN0YWxsQ2VydGlmaWNhdGVBdXRob3JpdHkob3B0aW9ucyk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLmdldENhQnVmZmVyIHx8IG9wdGlvbnMuZ2V0Q2FQYXRoKSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgXCJSb290IENBIGlzIG5vdCByZWFkYWJsZSwgYnV0IGl0IHByb2JhYmx5IGlzIGJlY2F1c2UgYW4gZWFybGllciB2ZXJzaW9uIG9mIGRldmNlcnQgbG9ja2VkIGl0LiBUcnlpbmcgdG8gZml4Li4uXCJcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgZW5zdXJlQ0FDZXJ0UmVhZGFibGUob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKCFleGlzdHMocGF0aEZvckRvbWFpbihkb21haW5QYXRoLCBgY2VydGlmaWNhdGUuY3J0YCkpKSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYENhbid0IGZpbmQgY2VydGlmaWNhdGUgZmlsZSBmb3IgJHtkb21haW5zfSwgc28gaXQgbXVzdCBiZSB0aGUgZmlyc3QgcmVxdWVzdCBmb3IgJHtkb21haW5zfS4gR2VuZXJhdGluZyBhbmQgY2FjaGluZyAuLi5gXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IGdlbmVyYXRlRG9tYWluQ2VydGlmaWNhdGUoZG9tYWlucyk7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnNraXBIb3N0c0ZpbGUpIHtcbiAgICAgICAgZG9tYWlucy5mb3JFYWNoKGFzeW5jIChkb21haW4pID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGN1cnJlbnRQbGF0Zm9ybS5hZGREb21haW5Ub0hvc3RGaWxlSWZNaXNzaW5nKGRvbWFpbik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGRlYnVnKGBSZXR1cm5pbmcgZG9tYWluIGNlcnRpZmljYXRlYCk7XG5cbiAgICBjb25zdCByZXQgPSB7XG4gICAgICAgIGtleTogcmVhZEZpbGUoZG9tYWluS2V5UGF0aCksXG4gICAgICAgIGNlcnQ6IHJlYWRGaWxlKGRvbWFpbkNlcnRQYXRoKSxcbiAgICB9IGFzIElSZXR1cm5EYXRhPE8+O1xuICAgIGlmIChvcHRpb25zLmdldENhQnVmZmVyKSAocmV0IGFzIHVua25vd24gYXMgSUNhQnVmZmVyKS5jYSA9IHJlYWRGaWxlKHJvb3RDQUNlcnRQYXRoKTtcbiAgICBpZiAob3B0aW9ucy5nZXRDYVBhdGgpIChyZXQgYXMgdW5rbm93biBhcyBJQ2FQYXRoKS5jYVBhdGggPSByb290Q0FDZXJ0UGF0aDtcblxuICAgIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNDZXJ0aWZpY2F0ZUZvcihyZXF1ZXN0ZWREb21haW5zOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGRvbWFpbnMgPSBBcnJheS5pc0FycmF5KHJlcXVlc3RlZERvbWFpbnMpID8gcmVxdWVzdGVkRG9tYWlucyA6IFtyZXF1ZXN0ZWREb21haW5zXTtcbiAgICBjb25zdCBkb21haW5QYXRoID0gZ2V0U3RhYmxlRG9tYWluUGF0aChkb21haW5zKTtcbiAgICByZXR1cm4gZXhpc3RzKHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgYGNlcnRpZmljYXRlLmNydGApKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbmZpZ3VyZWREb21haW5zKCkge1xuICAgIHJldHVybiByZWFkZGlyKGRvbWFpbnNEaXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYXRpb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29uZmlnRGlyO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVtb3ZlRG9tYWluKHJlcXVlc3RlZERvbWFpbnM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgZG9tYWlucyA9IEFycmF5LmlzQXJyYXkocmVxdWVzdGVkRG9tYWlucykgPyByZXF1ZXN0ZWREb21haW5zIDogW3JlcXVlc3RlZERvbWFpbnNdO1xuICAgIGF3YWl0IHJldm9rZURvbWFpbkNlcnRpZmljYXRlKGRvbWFpbnMpO1xuXG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoZG9tYWlucyk7XG4gICAgcmV0dXJuIHJpbXJhZi5zeW5jKHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlQWxsKCk6IHZvaWQge1xuICAgIHVuaW5zdGFsbCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FFeHBpcnlJbkRheXMoKTogbnVtYmVyIHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBjYUV4cGlyeURhdGEgPSBvcGVuc3NsKFsneDUwOScsICctaW4nLCByb290Q0FDZXJ0UGF0aCwgJy1ub291dCcsICctZW5kZGF0ZScgXSkudG9TdHJpbmcoKS50cmltKCk7XG4gICAgICAgIHJldHVybiBwYXJzZU9wZW5TU0xFeHBpcnlEYXRhKGNhRXhwaXJ5RGF0YSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjZXJ0aWZpY2F0ZUV4cGlyeUluRGF5cyhkb21haW46IHN0cmluZyk6IG51bWJlciB7XG4gICAgY29uc3QgZG9tYWluUGF0aCA9IGdldFN0YWJsZURvbWFpblBhdGgoW2RvbWFpbl0pO1xuICAgIGxldCBkb21haW5DZXJ0UGF0aCA9IHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgJ2NlcnRpZmljYXRlLmNydCcpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY2VydEV4cGlyeURhdGEgPSBvcGVuc3NsKFsneDUwOScsICctaW4nLCBkb21haW5DZXJ0UGF0aCwgJy1ub291dCcsICctZW5kZGF0ZScgXSkudG9TdHJpbmcoKS50cmltKCk7XG4gICAgICAgIHJldHVybiBwYXJzZU9wZW5TU0xFeHBpcnlEYXRhKGNlcnRFeHBpcnlEYXRhKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbn1cbiJdfQ==