devcert
Version:
Generate trusted local SSL/TLS certificates for local SSL development
102 lines • 16.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeDomain = exports.configuredDomains = exports.hasCertificateFor = exports.certificateFor = exports.uninstall = void 0;
const tslib_1 = require("tslib");
const fs_1 = require("fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const command_exists_1 = require("command-exists");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const constants_1 = require("./constants");
const platforms_1 = tslib_1.__importDefault(require("./platforms"));
const certificate_authority_1 = tslib_1.__importStar(require("./certificate-authority"));
Object.defineProperty(exports, "uninstall", { enumerable: true, get: function () { return certificate_authority_1.uninstall; } });
const certificates_1 = tslib_1.__importDefault(require("./certificates"));
const user_interface_1 = tslib_1.__importDefault(require("./user-interface"));
const is_valid_domain_1 = tslib_1.__importDefault(require("is-valid-domain"));
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.default(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 removeDomain(requestedDomains) {
const domains = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains];
const domainPath = constants_1.getStableDomainPath(domains);
return rimraf_1.default.sync(constants_1.pathForDomain(domainPath));
}
exports.removeDomain = removeDomain;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbImluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSwyQkFBNEY7QUFDNUYsMERBQWdDO0FBQ2hDLG1EQUF1RDtBQUN2RCw0REFBNEI7QUFDNUIsMkNBU3FCO0FBQ3JCLG9FQUEwQztBQUMxQyx5RkFBdUc7QUFJOUYsMEZBSm1ELGlDQUFTLE9BSW5EO0FBSGxCLDBFQUF1RDtBQUN2RCw4RUFBcUQ7QUFDckQsOEVBQTRDO0FBRzVDLE1BQU0sS0FBSyxHQUFHLGVBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQTZCckM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsU0FBc0IsY0FBYyxDQUFvQixnQkFBbUMsRUFBRSxVQUFhLEVBQU87O1FBQy9HLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN4RixPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDekIsSUFBSSxNQUFNLEtBQUssV0FBVyxJQUFJLENBQUMseUJBQWEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtnQkFDL0gsTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLE1BQU0sK0JBQStCLENBQUMsQ0FBQzthQUM1RDtRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxVQUFVLEdBQUcsK0JBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEQsS0FBSyxDQUFDLDZCQUE2QixPQUFPLGdDQUFnQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLDBCQUEwQixPQUFPLENBQUMsT0FBTyxD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Q0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN4RixNQUFNLFVBQVUsR0FBRywrQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxPQUFPLGdCQUFNLENBQUMsSUFBSSxDQUFDLHlCQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBSkQsb0NBSUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByZWFkRmlsZVN5bmMgYXMgcmVhZEZpbGUsIHJlYWRkaXJTeW5jIGFzIHJlYWRkaXIsIGV4aXN0c1N5bmMgYXMgZXhpc3RzIH0gZnJvbSAnZnMnO1xuaW1wb3J0IGNyZWF0ZURlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCB7IHN5bmMgYXMgY29tbWFuZEV4aXN0cyB9IGZyb20gJ2NvbW1hbmQtZXhpc3RzJztcbmltcG9ydCByaW1yYWYgZnJvbSAncmltcmFmJztcbmltcG9ydCB7XG4gIGlzTWFjLFxuICBpc0xpbnV4LFxuICBpc1dpbmRvd3MsXG4gIHBhdGhGb3JEb21haW4sXG4gIGdldFN0YWJsZURvbWFpblBhdGgsXG4gIGRvbWFpbnNEaXIsXG4gIHJvb3RDQUtleVBhdGgsXG4gIHJvb3RDQUNlcnRQYXRoLFxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgY3VycmVudFBsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm1zJztcbmltcG9ydCBpbnN0YWxsQ2VydGlmaWNhdGVBdXRob3JpdHksIHsgZW5zdXJlQ0FDZXJ0UmVhZGFibGUsIHVuaW5zdGFsbCB9IGZyb20gJy4vY2VydGlmaWNhdGUtYXV0aG9yaXR5JztcbmltcG9ydCBnZW5lcmF0ZURvbWFpbkNlcnRpZmljYXRlIGZyb20gJy4vY2VydGlmaWNhdGVzJztcbmltcG9ydCBVSSwgeyBVc2VySW50ZXJmYWNlIH0gZnJvbSAnLi91c2VyLWludGVyZmFjZSc7XG5pbXBvcnQgaXNWYWxpZERvbWFpbiBmcm9tICdpcy12YWxpZC1kb21haW4nO1xuZXhwb3J0IHsgdW5pbnN0YWxsIH07XG5cbmNvbnN0IGRlYnVnID0gY3JlYXRlRGVidWcoJ2RldmNlcnQnKTtcblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zIC8qIGV4dGVuZHMgUGFydGlhbDxJQ2FCdWZmZXJPcHRzICYgSUNhUGF0aE9wdHM+ICAqLyB7XG4gIC8qKiBSZXR1cm4gdGhlIENBIGNlcnRpZmljYXRlIGRhdGE/ICovXG4gIGdldENhQnVmZmVyPzogYm9vbGVhbjtcbiAgLyoqIFJldHVybiB0aGUgcGF0aCB0byB0aGUgQ0EgY2VydGlmaWNhdGU/ICovXG4gIGdldENhUGF0aD86IGJvb2xlYW47XG4gIC8qKiBJZiBgY2VydHV0aWxgIGlzIG5vdCBpbnN0YWxsZWQgYWxyZWFkeSAoZm9yIHVwZGF0aW5nIG5zcyBkYXRhYmFzZXM7IGUuZy4gZmlyZWZveCksIGRvIG5vdCBhdHRlbXB0IHRvIGluc3RhbGwgaXQgKi9cbiAgc2tpcENlcnR1dGlsSW5zdGFsbD86IGJvb2xlYW4sXG4gIC8qKiBEbyBub3QgdXBkYXRlIHlvdXIgc3lzdGVtcyBob3N0IGZpbGUgd2l0aCB0aGUgZG9tYWluIG5hbWUgb2YgdGhlIGNlcnRpZmljYXRlICovXG4gIHNraXBIb3N0c0ZpbGU/OiBib29sZWFuLFxuICAvKiogVXNlciBpbnRlcmZhY2UgaG9va3MgKi9cbiAgdWk/OiBVc2VySW50ZXJmYWNlXG59XG5cbmludGVyZmFjZSBJQ2FCdWZmZXIge1xuICBjYTogQnVmZmVyO1xufVxuaW50ZXJmYWNlIElDYVBhdGgge1xuICBjYVBhdGg6IHN0cmluZztcbn1cbmludGVyZmFjZSBJRG9tYWluRGF0YSB7XG4gIGtleTogQnVmZmVyO1xuICBjZXJ0OiBCdWZmZXI7XG59XG50eXBlIElSZXR1cm5DYTxPIGV4dGVuZHMgT3B0aW9ucz4gPSBPWydnZXRDYUJ1ZmZlciddIGV4dGVuZHMgdHJ1ZSA/IElDYUJ1ZmZlciA6IGZhbHNlO1xudHlwZSBJUmV0dXJuQ2FQYXRoPE8gZXh0ZW5kcyBPcHRpb25zPiA9IE9bJ2dldENhUGF0aCddIGV4dGVuZHMgdHJ1ZSA/IElDYVBhdGggOiBmYWxzZTtcbnR5cGUgSVJldHVybkRhdGE8TyBleHRlbmRzIE9wdGlvbnMgPSB7fT4gPSAoSURvbWFpbkRhdGEpICYgKElSZXR1cm5DYTxPPikgJiAoSVJldHVybkNhUGF0aDxPPik7XG5cbi8qKlxuICogUmVxdWVzdCBhbiBTU0wgY2VydGlmaWNhdGUgZm9yIHRoZSBnaXZlbiBhcHAgbmFtZSBzaWduZWQgYnkgdGhlIGRldmNlcnQgcm9vdFxuICogY2VydGlmaWNhdGUgYXV0aG9yaXR5LiBJZiBkZXZjZXJ0IGhhcyBwcmV2aW91c2x5IGdlbmVyYXRlZCBhIGNlcnRpZmljYXRlIGZvclxuICogdGhhdCBhcHAgbmFtZSBvbiB0aGlzIG1hY2hpbmUsIGl0IHdpbGwgcmV1c2UgdGhhdCBjZXJ0aWZpY2F0ZS5cbiAqXG4gKiBJZiB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lIGRldmNlcnQgaXMgYmVpbmcgcnVuIG9uIHRoaXMgbWFjaGluZSwgaXQgd2lsbFxuICogZ2VuZXJhdGUgYW5kIGF0dGVtcHQgdG8gaW5zdGFsbCBhIHJvb3QgY2VydGlmaWNhdGUgYXV0aG9yaXR5LlxuICpcbiAqIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB7IGtleSwgY2VydCB9LCB3aGVyZSBga2V5YCBhbmQgYGNlcnRgXG4gKiBhcmUgQnVmZmVycyB3aXRoIHRoZSBjb250ZW50cyBvZiB0aGUgY2VydGlmaWNhdGUgcHJpdmF0ZSBrZXkgYW5kIGNlcnRpZmljYXRlXG4gKiBmaWxlLCByZXNwZWN0aXZlbHlcbiAqIFxuICogSWYgYG9wdGlvbnMuZ2V0Q2FCdWZmZXJgIGlzIHRydWUsIHJldHVybiB2YWx1ZSB3aWxsIGluY2x1ZGUgdGhlIGNhIGNlcnRpZmljYXRlIGRhdGFcbiAqIGFzIHsgY2E6IEJ1ZmZlciB9XG4gKiBcbiAqIElmIGBvcHRpb25zLmdldENhUGF0aGAgaXMgdHJ1ZSwgcmV0dXJuIHZhbHVlIHdpbGwgaW5jbHVkZSB0aGUgY2EgY2VydGlmaWNhdGUgcGF0aFxuICogYXMgeyBjYVBhdGg6IHN0cmluZyB9XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjZXJ0aWZpY2F0ZUZvcjxPIGV4dGVuZHMgT3B0aW9ucz4ocmVxdWVzdGVkRG9tYWluczogc3RyaW5nIHwgc3RyaW5nW10sIG9wdGlvbnM6IE8gPSB7fSBhcyBPKTogUHJvbWlzZTxJUmV0dXJuRGF0YTxPPj4ge1xuICBjb25zdCBkb21haW5zID0gQXJyYXkuaXNBcnJheShyZXF1ZXN0ZWREb21haW5zKSA/IHJlcXVlc3RlZERvbWFpbnMgOiBbcmVxdWVzdGVkRG9tYWluc107XG4gIGRvbWFpbnMuZm9yRWFjaCgoZG9tYWluKSA9PiB7XG4gICAgaWYgKGRvbWFpbiAhPT0gXCJsb2NhbGhvc3RcIiAmJiAhaXNWYWxpZERvbWFpbihkb21haW4sIHsgc3ViZG9tYWluOiB0cnVlLCB3aWxkY2FyZDogZmFsc2UsIGFsbG93VW5pY29kZTogdHJ1ZSwgdG9wTGV2ZWw6IGZhbHNlIH0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFwiJHtkb21haW59XCIgaXMgbm90IGEgdmFsaWQgZG9tYWluIG5hbWUuYCk7XG4gICAgfVxuICB9KTtcblxuICBjb25zdCBkb21haW5QYXRoID0gZ2V0U3RhYmxlRG9tYWluUGF0aChkb21haW5zKTtcbiAgZGVidWcoYENlcnRpZmljYXRlIHJlcXVlc3RlZCBmb3IgJHtkb21haW5zfS4gU2tpcHBpbmcgY2VydHV0aWwgaW5zdGFsbDogJHtCb29sZWFuKG9wdGlvbnMuc2tpcENlcnR1dGlsSW5zdGFsbCl9LiBTa2lwcGluZyBob3N0cyBmaWxlOiAke0Jvb2xlYW4ob3B0aW9ucy5za2lwSG9zdHNGaWxlKX1gKTtcblxuICBpZiAob3B0aW9ucy51aSkge1xuICAgIE9iamVjdC5hc3NpZ24oVUksIG9wdGlvbnMudWkpO1xuICB9XG5cbiAgaWYgKCFpc01hYyAmJiAhaXNMaW51eCAmJiAhaXNXaW5kb3dzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBQbGF0Zm9ybSBub3Qgc3VwcG9ydGVkOiBcIiR7cHJvY2Vzcy5wbGF0Zm9ybX1cImApO1xuICB9XG5cbiAgaWYgKCFjb21tYW5kRXhpc3RzKCdvcGVuc3NsJykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ09wZW5TU0wgbm90IGZvdW5kOiBPcGVuU1NMIGlzIHJlcXVpcmVkIHRvIGdlbmVyYXRlIFNTTCBjZXJ0aWZpY2F0ZXMgLSBtYWtlIHN1cmUgaXQgaXMgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgaW4geW91ciBQQVRIJyk7XG4gIH1cblxuICBsZXQgZG9tYWluS2V5UGF0aCA9IHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgYHByaXZhdGUta2V5LmtleWApO1xuICBsZXQgZG9tYWluQ2VydFBhdGggPSBwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBjZXJ0aWZpY2F0ZS5jcnRgKTtcblxuICBpZiAoIWV4aXN0cyhyb290Q0FLZXlQYXRoKSkge1xuICAgIGRlYnVnKCdSb290IENBIGlzIG5vdCBpbnN0YWxsZWQgeWV0LCBzbyBpdCBtdXN0IGJlIG91ciBmaXJzdCBydW4uIEluc3RhbGxpbmcgcm9vdCBDQSAuLi4nKTtcbiAgICBhd2FpdCBpbnN0YWxsQ2VydGlmaWNhdGVBdXRob3JpdHkob3B0aW9ucyk7XG4gIH0gZWxzZSBpZiAob3B0aW9ucy5nZXRDYUJ1ZmZlciB8fCBvcHRpb25zLmdldENhUGF0aCkge1xuICAgIGRlYnVnKCdSb290IENBIGlzIG5vdCByZWFkYWJsZSwgYnV0IGl0IHByb2JhYmx5IGlzIGJlY2F1c2UgYW4gZWFybGllciB2ZXJzaW9uIG9mIGRldmNlcnQgbG9ja2VkIGl0LiBUcnlpbmcgdG8gZml4Li4uJyk7XG4gICAgYXdhaXQgZW5zdXJlQ0FDZXJ0UmVhZGFibGUob3B0aW9ucyk7XG4gIH1cblxuICBpZiAoIWV4aXN0cyhwYXRoRm9yRG9tYWluKGRvbWFpblBhdGgsIGBjZXJ0aWZpY2F0ZS5jcnRgKSkpIHtcbiAgICBkZWJ1ZyhgQ2FuJ3QgZmluZCBjZXJ0aWZpY2F0ZSBmaWxlIGZvciAke2RvbWFpbnN9LCBzbyBpdCBtdXN0IGJlIHRoZSBmaXJzdCByZXF1ZXN0IGZvciAke2RvbWFpbnN9LiBHZW5lcmF0aW5nIGFuZCBjYWNoaW5nIC4uLmApO1xuICAgIGF3YWl0IGdlbmVyYXRlRG9tYWluQ2VydGlmaWNhdGUoZG9tYWlucyk7XG4gIH1cblxuICBpZiAoIW9wdGlvbnMuc2tpcEhvc3RzRmlsZSkge1xuICAgIGRvbWFpbnMuZm9yRWFjaChhc3luYyAoZG9tYWluKSA9PiB7XG4gICAgICBhd2FpdCBjdXJyZW50UGxhdGZvcm0uYWRkRG9tYWluVG9Ib3N0RmlsZUlmTWlzc2luZyhkb21haW4pO1xuICAgIH0pXG4gIH1cblxuICBkZWJ1ZyhgUmV0dXJuaW5nIGRvbWFpbiBjZXJ0aWZpY2F0ZWApO1xuXG4gIGNvbnN0IHJldCA9IHtcbiAgICBrZXk6IHJlYWRGaWxlKGRvbWFpbktleVBhdGgpLFxuICAgIGNlcnQ6IHJlYWRGaWxlKGRvbWFpbkNlcnRQYXRoKVxuICB9IGFzIElSZXR1cm5EYXRhPE8+O1xuICBpZiAob3B0aW9ucy5nZXRDYUJ1ZmZlcikgKHJldCBhcyB1bmtub3duIGFzIElDYUJ1ZmZlcikuY2EgPSByZWFkRmlsZShyb290Q0FDZXJ0UGF0aCk7XG4gIGlmIChvcHRpb25zLmdldENhUGF0aCkgKHJldCBhcyB1bmtub3duIGFzIElDYVBhdGgpLmNhUGF0aCA9IHJvb3RDQUNlcnRQYXRoO1xuXG4gIHJldHVybiByZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNDZXJ0aWZpY2F0ZUZvcihyZXF1ZXN0ZWREb21haW5zOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICBjb25zdCBkb21haW5zID0gQXJyYXkuaXNBcnJheShyZXF1ZXN0ZWREb21haW5zKSA/IHJlcXVlc3RlZERvbWFpbnMgOiBbcmVxdWVzdGVkRG9tYWluc107XG4gIGNvbnN0IGRvbWFpblBhdGggPSBnZXRTdGFibGVEb21haW5QYXRoKGRvbWFpbnMpO1xuICByZXR1cm4gZXhpc3RzKHBhdGhGb3JEb21haW4oZG9tYWluUGF0aCwgYGNlcnRpZmljYXRlLmNydGApKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbmZpZ3VyZWREb21haW5zKCkge1xuICByZXR1cm4gcmVhZGRpcihkb21haW5zRGlyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZURvbWFpbihyZXF1ZXN0ZWREb21haW5zOiBzdHJpbmcgfCBzdHJpbmdbXSkge1xuICBjb25zdCBkb21haW5zID0gQXJyYXkuaXNBcnJheShyZXF1ZXN0ZWREb21haW5zKSA/IHJlcXVlc3RlZERvbWFpbnMgOiBbcmVxdWVzdGVkRG9tYWluc107XG4gIGNvbnN0IGRvbWFpblBhdGggPSBnZXRTdGFibGVEb21haW5QYXRoKGRvbWFpbnMpO1xuICByZXR1cm4gcmltcmFmLnN5bmMocGF0aEZvckRvbWFpbihkb21haW5QYXRoKSk7XG59XG4iXX0=
;