@expo/devcert 1.1.4 → 1.2.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.
@@ -1,33 +1,46 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const password_prompt_1 = tslib_1.__importDefault(require("password-prompt"));
6
+ const node_readline_1 = __importDefault(require("node:readline"));
5
7
  const utils_1 = require("./utils");
6
- const DefaultUI = {
7
- getWindowsEncryptionPassword() {
8
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
9
- return yield (0, password_prompt_1.default)('devcert password (http://bit.ly/devcert-what-password?):');
8
+ async function passwordPrompt(prompt) {
9
+ const input = node_readline_1.default.createInterface({
10
+ input: process.stdin,
11
+ output: process.stdout,
12
+ });
13
+ return new Promise((resolve, reject) => {
14
+ input.on('SIGINT', () => {
15
+ reject(new Error('SIGINT'));
16
+ });
17
+ input.question(prompt, (answer) => {
18
+ node_readline_1.default.moveCursor(process.stdout, 0, -1);
19
+ node_readline_1.default.clearLine(process.stdout, 0);
20
+ input.write(prompt + answer.replace(/./g, '*') + '\n');
21
+ input.close();
22
+ resolve(answer);
10
23
  });
24
+ });
25
+ }
26
+ const DefaultUI = {
27
+ async getWindowsEncryptionPassword() {
28
+ return await passwordPrompt('devcert password (http://bit.ly/devcert-what-password?):');
11
29
  },
12
- warnChromeOnLinuxWithoutCertutil() {
13
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
14
- console.warn(`
30
+ async warnChromeOnLinuxWithoutCertutil() {
31
+ console.warn(`
15
32
  WARNING: It looks like you have Chrome installed, but you specified
16
33
  'skipCertutilInstall: true'. Unfortunately, without installing
17
34
  certutil, it's impossible get Chrome to trust devcert's certificates
18
35
  The certificates will work, but Chrome will continue to warn you that
19
36
  they are untrusted.
20
37
  `);
21
- });
22
38
  },
23
- closeFirefoxBeforeContinuing() {
24
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
25
- console.log('Please close Firefox before continuing');
26
- });
39
+ async closeFirefoxBeforeContinuing() {
40
+ console.log('Please close Firefox before continuing');
27
41
  },
28
- startFirefoxWizard(certificateHost) {
29
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
30
- console.log(`
42
+ async startFirefoxWizard(certificateHost) {
43
+ console.log(`
31
44
  devcert was unable to automatically configure Firefox. You'll need to
32
45
  complete this process manually. Don't worry though - Firefox will walk
33
46
  you through it.
@@ -44,23 +57,19 @@ const DefaultUI = {
44
57
 
45
58
  <Press any key to launch Firefox wizard>
46
59
  `);
47
- yield (0, utils_1.waitForUser)();
48
- });
60
+ await (0, utils_1.waitForUser)();
49
61
  },
50
- firefoxWizardPromptPage(certificateURL) {
51
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
52
- return `
62
+ async firefoxWizardPromptPage(certificateURL) {
63
+ return `
53
64
  <html>
54
65
  <head>
55
66
  <meta http-equiv="refresh" content="0; url=${certificateURL}" />
56
67
  </head>
57
68
  </html>
58
69
  `;
59
- });
60
70
  },
61
- waitForFirefoxWizard() {
62
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
63
- console.log(`
71
+ async waitForFirefoxWizard() {
72
+ console.log(`
64
73
  Launching Firefox ...
65
74
 
66
75
  Great! Once you've finished the Firefox wizard for adding the devcert
@@ -68,9 +77,8 @@ const DefaultUI = {
68
77
 
69
78
  <Press any key to continue>
70
79
  `);
71
- yield (0, utils_1.waitForUser)();
72
- });
80
+ await (0, utils_1.waitForUser)();
73
81
  }
74
82
  };
75
83
  exports.default = DefaultUI;
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1pbnRlcmZhY2UuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInVzZXItaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDhFQUE2QztBQUM3QyxtQ0FBc0M7QUFXdEMsTUFBTSxTQUFTLEdBQWtCO0lBQ3pCLDRCQUE0Qjs7WUFDaEMsT0FBTyxNQUFNLElBQUEseUJBQWMsRUFBQywwREFBMEQsQ0FBQyxDQUFDO1FBQzFGLENBQUM7S0FBQTtJQUNLLGdDQUFnQzs7WUFDcEMsT0FBTyxDQUFDLElBQUksQ0FBQzs7Ozs7O0tBTVosQ0FBQyxDQUFDO1FBQ0wsQ0FBQztLQUFBO0lBQ0ssNEJBQTRCOztZQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7UUFDeEQsQ0FBQztLQUFBO0lBQ0ssa0JBQWtCLENBQUMsZUFBZTs7WUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7Ozs7Ozs7OztRQVVQLGVBQWdCOzs7Ozs7S0FNcEIsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxJQUFBLG1CQUFXLEdBQUUsQ0FBQztRQUN0QixDQUFDO0tBQUE7SUFDSyx1QkFBdUIsQ0FBQyxjQUFzQjs7WUFDbEQsT0FBTzs7O3VEQUc0QyxjQUFjOzs7S0FHaEUsQ0FBQztRQUNKLENBQUM7S0FBQTtJQUNLLG9CQUFvQjs7WUFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7Ozs7OztLQU9YLENBQUMsQ0FBQTtZQUNGLE1BQU0sSUFBQSxtQkFBVyxHQUFFLENBQUM7UUFDdEIsQ0FBQztLQUFBO0NBQ0YsQ0FBQTtBQUVELGtCQUFlLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXNzd29yZFByb21wdCBmcm9tICdwYXNzd29yZC1wcm9tcHQnO1xuaW1wb3J0IHsgd2FpdEZvclVzZXIgfSBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBVc2VySW50ZXJmYWNlIHtcbiAgZ2V0V2luZG93c0VuY3J5cHRpb25QYXNzd29yZCgpOiBQcm9taXNlPHN0cmluZz47XG4gIHdhcm5DaHJvbWVPbkxpbnV4V2l0aG91dENlcnR1dGlsKCk6IFByb21pc2U8dm9pZD47XG4gIGNsb3NlRmlyZWZveEJlZm9yZUNvbnRpbnVpbmcoKTogUHJvbWlzZTx2b2lkPjtcbiAgc3RhcnRGaXJlZm94V2l6YXJkKGNlcnRpZmljYXRlSG9zdDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgZmlyZWZveFdpemFyZFByb21wdFBhZ2UoY2VydGlmaWNhdGVVUkw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgd2FpdEZvckZpcmVmb3hXaXphcmQoKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuY29uc3QgRGVmYXVsdFVJOiBVc2VySW50ZXJmYWNlID0ge1xuICBhc3luYyBnZXRXaW5kb3dzRW5jcnlwdGlvblBhc3N3b3JkKCkge1xuICAgIHJldHVybiBhd2FpdCBwYXNzd29yZFByb21wdCgnZGV2Y2VydCBwYXNzd29yZCAoaHR0cDovL2JpdC5seS9kZXZjZXJ0LXdoYXQtcGFzc3dvcmQ/KTonKTtcbiAgfSxcbiAgYXN5bmMgd2FybkNocm9tZU9uTGludXhXaXRob3V0Q2VydHV0aWwoKSB7XG4gICAgY29uc29sZS53YXJuKGBcbiAgICAgIFdBUk5JTkc6IEl0IGxvb2tzIGxpa2UgeW91IGhhdmUgQ2hyb21lIGluc3RhbGxlZCwgYnV0IHlvdSBzcGVjaWZpZWRcbiAgICAgICdza2lwQ2VydHV0aWxJbnN0YWxsOiB0cnVlJy4gVW5mb3J0dW5hdGVseSwgd2l0aG91dCBpbnN0YWxsaW5nXG4gICAgICBjZXJ0dXRpbCwgaXQncyBpbXBvc3NpYmxlIGdldCBDaHJvbWUgdG8gdHJ1c3QgZGV2Y2VydCdzIGNlcnRpZmljYXRlc1xuICAgICAgVGhlIGNlcnRpZmljYXRlcyB3aWxsIHdvcmssIGJ1dCBDaHJvbWUgd2lsbCBjb250aW51ZSB0byB3YXJuIHlvdSB0aGF0XG4gICAgICB0aGV5IGFyZSB1bnRydXN0ZWQuXG4gICAgYCk7XG4gIH0sXG4gIGFzeW5jIGNsb3NlRmlyZWZveEJlZm9yZUNvbnRpbnVpbmcoKSB7XG4gICAgY29uc29sZS5sb2coJ1BsZWFzZSBjbG9zZSBGaXJlZm94IGJlZm9yZSBjb250aW51aW5nJyk7XG4gIH0sXG4gIGFzeW5jIHN0YXJ0RmlyZWZveFdpemFyZChjZXJ0aWZpY2F0ZUhvc3QpIHtcbiAgICBjb25zb2xlLmxvZyhgXG4gICAgICBkZXZjZXJ0IHdhcyB1bmFibGUgdG8gYXV0b21hdGljYWxseSBjb25maWd1cmUgRmlyZWZveC4gWW91J2xsIG5lZWQgdG9cbiAgICAgIGNvbXBsZXRlIHRoaXMgcHJvY2VzcyBtYW51YWxseS4gRG9uJ3Qgd29ycnkgdGhvdWdoIC0gRmlyZWZveCB3aWxsIHdhbGtcbiAgICAgIHlvdSB0aHJvdWdoIGl0LlxuXG4gICAgICBXaGVuIHlvdSdyZSByZWFkeSwgaGl0IGFueSBrZXkgdG8gY29udGludWUuIEZpcmVmb3ggd2lsbCBsYXVuY2ggYW5kXG4gICAgICBkaXNwbGF5IGEgd2l6YXJkIHRvIHdhbGsgeW91IHRocm91Z2ggaG93IHRvIHRydXN0IHRoZSBkZXZjZXJ0XG4gICAgICBjZXJ0aWZpY2F0ZS4gV2hlbiB5b3UgYXJlIGZpbmlzaGVkLCBjb21lIGJhY2sgaGVyZSBhbmQgd2UnbGwgZmluaXNoIHVwLlxuXG4gICAgICAoSWYgRmlyZWZveCBkb2Vzbid0IHN0YXJ0LCBnbyBhaGVhZCBhbmQgc3RhcnQgaXQgYW5kIG5hdmlnYXRlIHRvXG4gICAgICAkeyBjZXJ0aWZpY2F0ZUhvc3QgfSBpbiBhIG5ldyB0YWIuKVxuXG4gICAgICBJZiB5b3UgYXJlIGN1cmlvdXMgYWJvdXQgd2h5IGFsbCB0aGlzIGlzIG5lY2Vzc2FyeSwgY2hlY2sgb3V0XG4gICAgICBodHRwczovL2dpdGh1Yi5jb20vZGF2ZXdhc21lci9kZXZjZXJ0I2hvdy1pdC13b3Jrc1xuXG4gICAgICA8UHJlc3MgYW55IGtleSB0byBsYXVuY2ggRmlyZWZveCB3aXphcmQ+XG4gICAgYCk7XG4gICAgYXdhaXQgd2FpdEZvclVzZXIoKTtcbiAgfSxcbiAgYXN5bmMgZmlyZWZveFdpemFyZFByb21wdFBhZ2UoY2VydGlmaWNhdGVVUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgXG4gICAgICA8aHRtbD5cbiAgICAgICAgPGhlYWQ+XG4gICAgICAgICAgPG1ldGEgaHR0cC1lcXVpdj1cInJlZnJlc2hcIiBjb250ZW50PVwiMDsgdXJsPSR7Y2VydGlmaWNhdGVVUkx9XCIgLz5cbiAgICAgICAgPC9oZWFkPlxuICAgICAgPC9odG1sPlxuICAgIGA7XG4gIH0sXG4gIGFzeW5jIHdhaXRGb3JGaXJlZm94V2l6YXJkKCkge1xuICAgIGNvbnNvbGUubG9nKGBcbiAgICAgIExhdW5jaGluZyBGaXJlZm94IC4uLlxuXG4gICAgICBHcmVhdCEgT25jZSB5b3UndmUgZmluaXNoZWQgdGhlIEZpcmVmb3ggd2l6YXJkIGZvciBhZGRpbmcgdGhlIGRldmNlcnRcbiAgICAgIGNlcnRpZmljYXRlLCBqdXN0IGhpdCBhbnkga2V5IGhlcmUgYWdhaW4gYW5kIHdlJ2xsIHdyYXAgdXAuXG5cbiAgICAgIDxQcmVzcyBhbnkga2V5IHRvIGNvbnRpbnVlPlxuICAgIGApXG4gICAgYXdhaXQgd2FpdEZvclVzZXIoKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBEZWZhdWx0VUk7Il19
84
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1pbnRlcmZhY2UuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInVzZXItaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0VBQXFDO0FBQ3JDLG1DQUFzQztBQVd0QyxLQUFLLFVBQVUsY0FBYyxDQUFDLE1BQWM7SUFDMUMsTUFBTSxLQUFLLEdBQUcsdUJBQVEsQ0FBQyxlQUFlLENBQUM7UUFDckMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1FBQ3BCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtLQUN2QixDQUFDLENBQUM7SUFDSCxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ3JDLEtBQUssQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtZQUN0QixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDaEMsdUJBQVEsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzQyx1QkFBUSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ3ZELEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNkLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQU0sU0FBUyxHQUFrQjtJQUMvQixLQUFLLENBQUMsNEJBQTRCO1FBQ2hDLE9BQU8sTUFBTSxjQUFjLENBQUMsMERBQTBELENBQUMsQ0FBQztJQUMxRixDQUFDO0lBQ0QsS0FBSyxDQUFDLGdDQUFnQztRQUNwQyxPQUFPLENBQUMsSUFBSSxDQUFDOzs7Ozs7S0FNWixDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ0QsS0FBSyxDQUFDLDRCQUE0QjtRQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUNELEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlO1FBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUM7Ozs7Ozs7Ozs7UUFVUCxlQUFnQjs7Ozs7O0tBTXBCLENBQUMsQ0FBQztRQUNILE1BQU0sSUFBQSxtQkFBVyxHQUFFLENBQUM7SUFDdEIsQ0FBQztJQUNELEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxjQUFzQjtRQUNsRCxPQUFPOzs7dURBRzRDLGNBQWM7OztLQUdoRSxDQUFDO0lBQ0osQ0FBQztJQUNELEtBQUssQ0FBQyxvQkFBb0I7UUFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7Ozs7OztLQU9YLENBQUMsQ0FBQTtRQUNGLE1BQU0sSUFBQSxtQkFBVyxHQUFFLENBQUM7SUFDdEIsQ0FBQztDQUNGLENBQUE7QUFFRCxrQkFBZSxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcmVhZGxpbmUgZnJvbSAnbm9kZTpyZWFkbGluZSc7XG5pbXBvcnQgeyB3YWl0Rm9yVXNlciB9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFVzZXJJbnRlcmZhY2Uge1xuICBnZXRXaW5kb3dzRW5jcnlwdGlvblBhc3N3b3JkKCk6IFByb21pc2U8c3RyaW5nPjtcbiAgd2FybkNocm9tZU9uTGludXhXaXRob3V0Q2VydHV0aWwoKTogUHJvbWlzZTx2b2lkPjtcbiAgY2xvc2VGaXJlZm94QmVmb3JlQ29udGludWluZygpOiBQcm9taXNlPHZvaWQ+O1xuICBzdGFydEZpcmVmb3hXaXphcmQoY2VydGlmaWNhdGVIb3N0OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICBmaXJlZm94V2l6YXJkUHJvbXB0UGFnZShjZXJ0aWZpY2F0ZVVSTDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+O1xuICB3YWl0Rm9yRmlyZWZveFdpemFyZCgpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXNzd29yZFByb21wdChwcm9tcHQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGlucHV0ID0gcmVhZGxpbmUuY3JlYXRlSW50ZXJmYWNlKHtcbiAgICBpbnB1dDogcHJvY2Vzcy5zdGRpbixcbiAgICBvdXRwdXQ6IHByb2Nlc3Muc3Rkb3V0LFxuICB9KTtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBpbnB1dC5vbignU0lHSU5UJywgKCkgPT4ge1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcignU0lHSU5UJykpO1xuICAgIH0pO1xuICAgIGlucHV0LnF1ZXN0aW9uKHByb21wdCwgKGFuc3dlcikgPT4ge1xuICAgICAgcmVhZGxpbmUubW92ZUN1cnNvcihwcm9jZXNzLnN0ZG91dCwgMCwgLTEpO1xuICAgICAgcmVhZGxpbmUuY2xlYXJMaW5lKHByb2Nlc3Muc3Rkb3V0LCAwKTtcbiAgICAgIGlucHV0LndyaXRlKHByb21wdCArIGFuc3dlci5yZXBsYWNlKC8uL2csICcqJykgKyAnXFxuJyk7XG4gICAgICBpbnB1dC5jbG9zZSgpO1xuICAgICAgcmVzb2x2ZShhbnN3ZXIpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuY29uc3QgRGVmYXVsdFVJOiBVc2VySW50ZXJmYWNlID0ge1xuICBhc3luYyBnZXRXaW5kb3dzRW5jcnlwdGlvblBhc3N3b3JkKCkge1xuICAgIHJldHVybiBhd2FpdCBwYXNzd29yZFByb21wdCgnZGV2Y2VydCBwYXNzd29yZCAoaHR0cDovL2JpdC5seS9kZXZjZXJ0LXdoYXQtcGFzc3dvcmQ/KTonKTtcbiAgfSxcbiAgYXN5bmMgd2FybkNocm9tZU9uTGludXhXaXRob3V0Q2VydHV0aWwoKSB7XG4gICAgY29uc29sZS53YXJuKGBcbiAgICAgIFdBUk5JTkc6IEl0IGxvb2tzIGxpa2UgeW91IGhhdmUgQ2hyb21lIGluc3RhbGxlZCwgYnV0IHlvdSBzcGVjaWZpZWRcbiAgICAgICdza2lwQ2VydHV0aWxJbnN0YWxsOiB0cnVlJy4gVW5mb3J0dW5hdGVseSwgd2l0aG91dCBpbnN0YWxsaW5nXG4gICAgICBjZXJ0dXRpbCwgaXQncyBpbXBvc3NpYmxlIGdldCBDaHJvbWUgdG8gdHJ1c3QgZGV2Y2VydCdzIGNlcnRpZmljYXRlc1xuICAgICAgVGhlIGNlcnRpZmljYXRlcyB3aWxsIHdvcmssIGJ1dCBDaHJvbWUgd2lsbCBjb250aW51ZSB0byB3YXJuIHlvdSB0aGF0XG4gICAgICB0aGV5IGFyZSB1bnRydXN0ZWQuXG4gICAgYCk7XG4gIH0sXG4gIGFzeW5jIGNsb3NlRmlyZWZveEJlZm9yZUNvbnRpbnVpbmcoKSB7XG4gICAgY29uc29sZS5sb2coJ1BsZWFzZSBjbG9zZSBGaXJlZm94IGJlZm9yZSBjb250aW51aW5nJyk7XG4gIH0sXG4gIGFzeW5jIHN0YXJ0RmlyZWZveFdpemFyZChjZXJ0aWZpY2F0ZUhvc3QpIHtcbiAgICBjb25zb2xlLmxvZyhgXG4gICAgICBkZXZjZXJ0IHdhcyB1bmFibGUgdG8gYXV0b21hdGljYWxseSBjb25maWd1cmUgRmlyZWZveC4gWW91J2xsIG5lZWQgdG9cbiAgICAgIGNvbXBsZXRlIHRoaXMgcHJvY2VzcyBtYW51YWxseS4gRG9uJ3Qgd29ycnkgdGhvdWdoIC0gRmlyZWZveCB3aWxsIHdhbGtcbiAgICAgIHlvdSB0aHJvdWdoIGl0LlxuXG4gICAgICBXaGVuIHlvdSdyZSByZWFkeSwgaGl0IGFueSBrZXkgdG8gY29udGludWUuIEZpcmVmb3ggd2lsbCBsYXVuY2ggYW5kXG4gICAgICBkaXNwbGF5IGEgd2l6YXJkIHRvIHdhbGsgeW91IHRocm91Z2ggaG93IHRvIHRydXN0IHRoZSBkZXZjZXJ0XG4gICAgICBjZXJ0aWZpY2F0ZS4gV2hlbiB5b3UgYXJlIGZpbmlzaGVkLCBjb21lIGJhY2sgaGVyZSBhbmQgd2UnbGwgZmluaXNoIHVwLlxuXG4gICAgICAoSWYgRmlyZWZveCBkb2Vzbid0IHN0YXJ0LCBnbyBhaGVhZCBhbmQgc3RhcnQgaXQgYW5kIG5hdmlnYXRlIHRvXG4gICAgICAkeyBjZXJ0aWZpY2F0ZUhvc3QgfSBpbiBhIG5ldyB0YWIuKVxuXG4gICAgICBJZiB5b3UgYXJlIGN1cmlvdXMgYWJvdXQgd2h5IGFsbCB0aGlzIGlzIG5lY2Vzc2FyeSwgY2hlY2sgb3V0XG4gICAgICBodHRwczovL2dpdGh1Yi5jb20vZGF2ZXdhc21lci9kZXZjZXJ0I2hvdy1pdC13b3Jrc1xuXG4gICAgICA8UHJlc3MgYW55IGtleSB0byBsYXVuY2ggRmlyZWZveCB3aXphcmQ+XG4gICAgYCk7XG4gICAgYXdhaXQgd2FpdEZvclVzZXIoKTtcbiAgfSxcbiAgYXN5bmMgZmlyZWZveFdpemFyZFByb21wdFBhZ2UoY2VydGlmaWNhdGVVUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgXG4gICAgICA8aHRtbD5cbiAgICAgICAgPGhlYWQ+XG4gICAgICAgICAgPG1ldGEgaHR0cC1lcXVpdj1cInJlZnJlc2hcIiBjb250ZW50PVwiMDsgdXJsPSR7Y2VydGlmaWNhdGVVUkx9XCIgLz5cbiAgICAgICAgPC9oZWFkPlxuICAgICAgPC9odG1sPlxuICAgIGA7XG4gIH0sXG4gIGFzeW5jIHdhaXRGb3JGaXJlZm94V2l6YXJkKCkge1xuICAgIGNvbnNvbGUubG9nKGBcbiAgICAgIExhdW5jaGluZyBGaXJlZm94IC4uLlxuXG4gICAgICBHcmVhdCEgT25jZSB5b3UndmUgZmluaXNoZWQgdGhlIEZpcmVmb3ggd2l6YXJkIGZvciBhZGRpbmcgdGhlIGRldmNlcnRcbiAgICAgIGNlcnRpZmljYXRlLCBqdXN0IGhpdCBhbnkga2V5IGhlcmUgYWdhaW4gYW5kIHdlJ2xsIHdyYXAgdXAuXG5cbiAgICAgIDxQcmVzcyBhbnkga2V5IHRvIGNvbnRpbnVlPlxuICAgIGApXG4gICAgYXdhaXQgd2FpdEZvclVzZXIoKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBEZWZhdWx0VUk7XG4iXX0=
package/dist/utils.d.ts CHANGED
@@ -6,3 +6,4 @@ export declare function waitForUser(): Promise<unknown>;
6
6
  export declare function reportableError(message: string): Error;
7
7
  export declare function mktmp(): string;
8
8
  export declare function sudo(cmd: string): Promise<string | null>;
9
+ export declare function commandExists(command: string): string | null;
package/dist/utils.js CHANGED
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.openssl = openssl;
4
7
  exports.run = run;
@@ -7,12 +10,14 @@ exports.waitForUser = waitForUser;
7
10
  exports.reportableError = reportableError;
8
11
  exports.mktmp = mktmp;
9
12
  exports.sudo = sudo;
10
- const tslib_1 = require("tslib");
13
+ exports.commandExists = commandExists;
11
14
  const child_process_1 = require("child_process");
12
- const tmp_1 = tslib_1.__importDefault(require("tmp"));
13
- const debug_1 = tslib_1.__importDefault(require("debug"));
14
- const path_1 = tslib_1.__importDefault(require("path"));
15
- const sudo_prompt_1 = tslib_1.__importDefault(require("sudo-prompt"));
15
+ const crypto_1 = require("crypto");
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const os_1 = __importDefault(require("os"));
18
+ const debug_1 = __importDefault(require("debug"));
19
+ const path_1 = __importDefault(require("path"));
20
+ const sudo_prompt_1 = __importDefault(require("@expo/sudo-prompt"));
16
21
  const constants_1 = require("./constants");
17
22
  const debug = (0, debug_1.default)('devcert:util');
18
23
  function openssl(args) {
@@ -42,9 +47,10 @@ function reportableError(message) {
42
47
  return new Error(`${message} | This is a bug in devcert, please report the issue at https://github.com/davewasmer/devcert/issues`);
43
48
  }
44
49
  function mktmp() {
45
- // discardDescriptor because windows complains the file is in use if we create a tmp file
46
- // and then shell out to a process that tries to use it
47
- return tmp_1.default.fileSync({ discardDescriptor: true }).name;
50
+ const random = (0, crypto_1.randomBytes)(6).toString('hex');
51
+ const tmppath = path_1.default.join(os_1.default.tmpdir(), `tmp-${process.pid}${random}`);
52
+ fs_1.default.closeSync(fs_1.default.openSync(tmppath, 'w'));
53
+ return tmppath;
48
54
  }
49
55
  function sudo(cmd) {
50
56
  return new Promise((resolve, reject) => {
@@ -54,4 +60,23 @@ function sudo(cmd) {
54
60
  });
55
61
  });
56
62
  }
57
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBVUEsMEJBT0M7QUFFRCxrQkFHQztBQUVELGdDQUlDO0FBRUQsa0NBS0M7QUFFRCwwQ0FFQztBQUVELHNCQUlDO0FBRUQsb0JBT0M7O0FBdERELGlEQUFrRTtBQUNsRSxzREFBc0I7QUFDdEIsMERBQWdDO0FBQ2hDLHdEQUF3QjtBQUN4QixzRUFBcUM7QUFFckMsMkNBQXlDO0FBRXpDLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBVyxFQUFDLGNBQWMsQ0FBQyxDQUFDO0FBRTFDLFNBQWdCLE9BQU8sQ0FBQyxJQUFjO0lBQ3BDLE9BQU8sR0FBRyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUU7UUFDMUIsS0FBSyxFQUFFLE1BQU07UUFDYixHQUFHLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUNqQixRQUFRLEVBQUUsY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFBLHNCQUFVLEVBQUMsTUFBTSxDQUFDLENBQUM7U0FDeEMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDO0tBQ2hCLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFnQixHQUFHLENBQUMsR0FBVyxFQUFFLElBQWMsRUFBRSxVQUErQixFQUFFO0lBQ2hGLEtBQUssQ0FBQyxtQkFBb0IsR0FBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RELE9BQU8sSUFBQSw0QkFBWSxFQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUVELFNBQWdCLFVBQVUsQ0FBQyxJQUFZLEVBQUUsS0FBbUM7SUFDMUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUU7UUFDL0IsS0FBSztLQUNOLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFnQixXQUFXO0lBQ3pCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFnQixlQUFlLENBQUMsT0FBZTtJQUM3QyxPQUFPLElBQUksS0FBSyxDQUFDLEdBQUcsT0FBTyxzR0FBc0csQ0FBQyxDQUFDO0FBQ3JJLENBQUM7QUFFRCxTQUFnQixLQUFLO0lBQ25CLHlGQUF5RjtJQUN6Rix1REFBdUQ7SUFDdkQsT0FBTyxhQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDeEQsQ0FBQztBQUVELFNBQWdCLElBQUksQ0FBQyxHQUFXO0lBQzlCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMscUJBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFLENBQUMsR0FBaUIsRUFBRSxNQUFxQixFQUFFLE1BQXFCLEVBQUUsRUFBRTtZQUM1RyxJQUFJLEtBQUssR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBRTtZQUNsRyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlY0ZpbGVTeW5jLCBFeGVjRmlsZVN5bmNPcHRpb25zIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgdG1wIGZyb20gJ3RtcCc7XG5pbXBvcnQgY3JlYXRlRGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgc3Vkb1Byb21wdCBmcm9tICdzdWRvLXByb21wdCc7XG5cbmltcG9ydCB7IGNvbmZpZ1BhdGggfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbmNvbnN0IGRlYnVnID0gY3JlYXRlRGVidWcoJ2RldmNlcnQ6dXRpbCcpO1xuXG5leHBvcnQgZnVuY3Rpb24gb3BlbnNzbChhcmdzOiBzdHJpbmdbXSkge1xuICByZXR1cm4gcnVuKCdvcGVuc3NsJywgYXJncywge1xuICAgIHN0ZGlvOiAncGlwZScsXG4gICAgZW52OiBPYmplY3QuYXNzaWduKHtcbiAgICAgIFJBTkRGSUxFOiBwYXRoLmpvaW4oY29uZmlnUGF0aCgnLnJuZCcpKVxuICAgIH0sIHByb2Nlc3MuZW52KVxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJ1bihjbWQ6IHN0cmluZywgYXJnczogc3RyaW5nW10sIG9wdGlvbnM6IEV4ZWNGaWxlU3luY09wdGlvbnMgPSB7fSkge1xuICBkZWJ1ZyhgZXhlY0ZpbGVTeW5jOiBcXGAkeyBjbWQgfSAke2FyZ3Muam9pbignICcpfVxcYGApO1xuICByZXR1cm4gZXhlY0ZpbGVTeW5jKGNtZCwgYXJncywgb3B0aW9ucyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdWRvQXBwZW5kKGZpbGU6IHN0cmluZywgaW5wdXQ6IEV4ZWNGaWxlU3luY09wdGlvbnNbXCJpbnB1dFwiXSkge1xuICBydW4oJ3N1ZG8nLCBbJ3RlZScsICctYScsIGZpbGVdLCB7XG4gICAgaW5wdXRcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3YWl0Rm9yVXNlcigpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgcHJvY2Vzcy5zdGRpbi5yZXN1bWUoKTtcbiAgICBwcm9jZXNzLnN0ZGluLm9uKCdkYXRhJywgcmVzb2x2ZSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVwb3J0YWJsZUVycm9yKG1lc3NhZ2U6IHN0cmluZykge1xuICByZXR1cm4gbmV3IEVycm9yKGAke21lc3NhZ2V9IHwgVGhpcyBpcyBhIGJ1ZyBpbiBkZXZjZXJ0LCBwbGVhc2UgcmVwb3J0IHRoZSBpc3N1ZSBhdCBodHRwczovL2dpdGh1Yi5jb20vZGF2ZXdhc21lci9kZXZjZXJ0L2lzc3Vlc2ApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWt0bXAoKSB7XG4gIC8vIGRpc2NhcmREZXNjcmlwdG9yIGJlY2F1c2Ugd2luZG93cyBjb21wbGFpbnMgdGhlIGZpbGUgaXMgaW4gdXNlIGlmIHdlIGNyZWF0ZSBhIHRtcCBmaWxlXG4gIC8vIGFuZCB0aGVuIHNoZWxsIG91dCB0byBhIHByb2Nlc3MgdGhhdCB0cmllcyB0byB1c2UgaXRcbiAgcmV0dXJuIHRtcC5maWxlU3luYyh7IGRpc2NhcmREZXNjcmlwdG9yOiB0cnVlIH0pLm5hbWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdWRvKGNtZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc3Vkb1Byb21wdC5leGVjKGNtZCwgeyBuYW1lOiAnZGV2Y2VydCcgfSwgKGVycjogRXJyb3IgfCBudWxsLCBzdGRvdXQ6IHN0cmluZyB8IG51bGwsIHN0ZGVycjogc3RyaW5nIHwgbnVsbCkgPT4ge1xuICAgICAgbGV0IGVycm9yID0gZXJyIHx8ICh0eXBlb2Ygc3RkZXJyID09PSAnc3RyaW5nJyAmJiBzdGRlcnIudHJpbSgpLmxlbmd0aCA+IDAgJiYgbmV3IEVycm9yKHN0ZGVycikpIDtcbiAgICAgIGVycm9yID8gcmVqZWN0KGVycm9yKSA6IHJlc29sdmUoc3Rkb3V0KTtcbiAgICB9KTtcbiAgfSk7XG59XG4iXX0=
63
+ const _commands = {};
64
+ function commandExists(command) {
65
+ if (_commands[command] !== undefined) {
66
+ return _commands[command];
67
+ }
68
+ const paths = process.env[constants_1.isWindows ? 'Path' : 'PATH'].split(path_1.default.delimiter);
69
+ const extensions = [...(process.env.PATHEXT || '').split(path_1.default.delimiter), ''];
70
+ for (const dir of paths) {
71
+ for (const extension of extensions) {
72
+ const filePath = path_1.default.join(dir, command + extension);
73
+ try {
74
+ fs_1.default.accessSync(filePath, fs_1.default.constants.X_OK);
75
+ return (_commands[command] = filePath);
76
+ }
77
+ catch (_a) { }
78
+ }
79
+ }
80
+ return (_commands[command] = null);
81
+ }
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBWUEsMEJBT0M7QUFFRCxrQkFHQztBQUVELGdDQUlDO0FBRUQsa0NBS0M7QUFFRCwwQ0FFQztBQUVELHNCQUtDO0FBRUQsb0JBT0M7QUFJRCxzQ0FnQkM7QUE3RUQsaURBQWtFO0FBQ2xFLG1DQUFxQztBQUNyQyw0Q0FBb0I7QUFDcEIsNENBQW9CO0FBQ3BCLGtEQUFnQztBQUNoQyxnREFBd0I7QUFDeEIsb0VBQTJDO0FBRTNDLDJDQUFvRDtBQUVwRCxNQUFNLEtBQUssR0FBRyxJQUFBLGVBQVcsRUFBQyxjQUFjLENBQUMsQ0FBQztBQUUxQyxTQUFnQixPQUFPLENBQUMsSUFBYztJQUNwQyxPQUFPLEdBQUcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFO1FBQzFCLEtBQUssRUFBRSxNQUFNO1FBQ2IsR0FBRyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDakIsUUFBUSxFQUFFLGNBQUksQ0FBQyxJQUFJLENBQUMsSUFBQSxzQkFBVSxFQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3hDLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQztLQUNoQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBZ0IsR0FBRyxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFBK0IsRUFBRTtJQUNoRixLQUFLLENBQUMsbUJBQW9CLEdBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0RCxPQUFPLElBQUEsNEJBQVksRUFBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFFRCxTQUFnQixVQUFVLENBQUMsSUFBWSxFQUFFLEtBQW1DO0lBQzFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFO1FB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LEdBQUcsUUFBUSxDQUFDLENBQUM7WUFDekMsQ0FBQztZQUFDLFdBQU0sQ0FBQyxDQUFBLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWNGaWxlU3luYywgRXhlY0ZpbGVTeW5jT3B0aW9ucyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBvcyBmcm9tICdvcyc7XG5pbXBvcnQgY3JlYXRlRGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgc3Vkb1Byb21wdCBmcm9tICdAZXhwby9zdWRvLXByb21wdCc7XG5cbmltcG9ydCB7IGNvbmZpZ1BhdGgsIGlzV2luZG93cyB9IGZyb20gJy4vY29uc3RhbnRzJztcblxuY29uc3QgZGVidWcgPSBjcmVhdGVEZWJ1ZygnZGV2Y2VydDp1dGlsJyk7XG5cbmV4cG9ydCBmdW5jdGlvbiBvcGVuc3NsKGFyZ3M6IHN0cmluZ1tdKSB7XG4gIHJldHVybiBydW4oJ29wZW5zc2wnLCBhcmdzLCB7XG4gICAgc3RkaW86ICdwaXBlJyxcbiAgICBlbnY6IE9iamVjdC5hc3NpZ24oe1xuICAgICAgUkFOREZJTEU6IHBhdGguam9pbihjb25maWdQYXRoKCcucm5kJykpXG4gICAgfSwgcHJvY2Vzcy5lbnYpXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuKGNtZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSwgb3B0aW9uczogRXhlY0ZpbGVTeW5jT3B0aW9ucyA9IHt9KSB7XG4gIGRlYnVnKGBleGVjRmlsZVN5bmM6IFxcYCR7IGNtZCB9ICR7YXJncy5qb2luKCcgJyl9XFxgYCk7XG4gIHJldHVybiBleGVjRmlsZVN5bmMoY21kLCBhcmdzLCBvcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN1ZG9BcHBlbmQoZmlsZTogc3RyaW5nLCBpbnB1dDogRXhlY0ZpbGVTeW5jT3B0aW9uc1tcImlucHV0XCJdKSB7XG4gIHJ1bignc3VkbycsIFsndGVlJywgJy1hJywgZmlsZV0sIHtcbiAgICBpbnB1dFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdhaXRGb3JVc2VyKCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBwcm9jZXNzLnN0ZGluLnJlc3VtZSgpO1xuICAgIHByb2Nlc3Muc3RkaW4ub24oJ2RhdGEnLCByZXNvbHZlKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXBvcnRhYmxlRXJyb3IobWVzc2FnZTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgRXJyb3IoYCR7bWVzc2FnZX0gfCBUaGlzIGlzIGEgYnVnIGluIGRldmNlcnQsIHBsZWFzZSByZXBvcnQgdGhlIGlzc3VlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9kYXZld2FzbWVyL2RldmNlcnQvaXNzdWVzYCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBta3RtcCgpIHtcbiAgY29uc3QgcmFuZG9tID0gcmFuZG9tQnl0ZXMoNikudG9TdHJpbmcoJ2hleCcpO1xuICBjb25zdCB0bXBwYXRoID0gcGF0aC5qb2luKG9zLnRtcGRpcigpLCBgdG1wLSR7cHJvY2Vzcy5waWR9JHtyYW5kb219YCk7XG4gIGZzLmNsb3NlU3luYyhmcy5vcGVuU3luYyh0bXBwYXRoLCAndycpKTtcbiAgcmV0dXJuIHRtcHBhdGg7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdWRvKGNtZDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc3Vkb1Byb21wdC5leGVjKGNtZCwgeyBuYW1lOiAnZGV2Y2VydCcgfSwgKGVycjogRXJyb3IgfCBudWxsLCBzdGRvdXQ6IHN0cmluZyB8IG51bGwsIHN0ZGVycjogc3RyaW5nIHwgbnVsbCkgPT4ge1xuICAgICAgbGV0IGVycm9yID0gZXJyIHx8ICh0eXBlb2Ygc3RkZXJyID09PSAnc3RyaW5nJyAmJiBzdGRlcnIudHJpbSgpLmxlbmd0aCA+IDAgJiYgbmV3IEVycm9yKHN0ZGVycikpIDtcbiAgICAgIGVycm9yID8gcmVqZWN0KGVycm9yKSA6IHJlc29sdmUoc3Rkb3V0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmNvbnN0IF9jb21tYW5kczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVsbD4gPSB7fTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbW1hbmRFeGlzdHMoY29tbWFuZDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmIChfY29tbWFuZHNbY29tbWFuZF0gIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBfY29tbWFuZHNbY29tbWFuZF07XG4gIH1cbiAgY29uc3QgcGF0aHMgPSBwcm9jZXNzLmVudltpc1dpbmRvd3MgPyAnUGF0aCcgOiAnUEFUSCddLnNwbGl0KHBhdGguZGVsaW1pdGVyKTtcbiAgY29uc3QgZXh0ZW5zaW9ucyA9IFsuLi4ocHJvY2Vzcy5lbnYuUEFUSEVYVCB8fCAnJykuc3BsaXQocGF0aC5kZWxpbWl0ZXIpLCAnJ107XG4gIGZvciAoY29uc3QgZGlyIG9mIHBhdGhzKSB7XG4gICAgZm9yIChjb25zdCBleHRlbnNpb24gb2YgZXh0ZW5zaW9ucykge1xuICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4oZGlyLCBjb21tYW5kICsgZXh0ZW5zaW9uKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZzLmFjY2Vzc1N5bmMoZmlsZVBhdGgsIGZzLmNvbnN0YW50cy5YX09LKTtcbiAgICAgICAgcmV0dXJuIChfY29tbWFuZHNbY29tbWFuZF0gPSBmaWxlUGF0aCk7XG4gICAgICB9IGNhdGNoIHt9XG4gICAgfVxuICB9XG4gIHJldHVybiAoX2NvbW1hbmRzW2NvbW1hbmRdID0gbnVsbCk7XG59XG4iXX0=
@@ -13,7 +13,7 @@ distinguished_name = req_distinguished_name
13
13
  req_extensions = req_extensions
14
14
 
15
15
  [ req_distinguished_name ]
16
- CN = <%= domain %>
16
+ CN = %DOMAIN%
17
17
 
18
18
  [ req_extensions ]
19
19
  basicConstraints = CA:FALSE
@@ -21,5 +21,5 @@ subjectAltName = @subject_alt_names
21
21
  subjectKeyIdentifier = hash
22
22
 
23
23
  [ subject_alt_names ]
24
- DNS.1 = <%= domain %>
25
- DNS.2 = *.<%= domain %>
24
+ DNS.1 = %DOMAIN%
25
+ DNS.2 = *.%DOMAIN%
@@ -3,11 +3,11 @@ default_ca = devcert_ca
3
3
 
4
4
  [ devcert_ca ]
5
5
  # Serial file that counts up unique IDs for each cert issued
6
- serial = <%= serialFile.replace(/\\/g, '\\\\') %>
6
+ serial = %SERIALFILE%
7
7
  # Database file that tracks all issued certs
8
- database = <%= databaseFile.replace(/\\/g, '\\\\') %>
8
+ database = %DATABASEFILE%
9
9
  # Where to put the new cert
10
- new_certs_dir = <%= domainDir.replace(/\\/g, '\\\\') %>
10
+ new_certs_dir = %DOMAINDIR%
11
11
  # Which algorithm to use
12
12
  default_md = sha256
13
13
  # Don't prompt the TTY for input, just use the config file values
@@ -35,5 +35,5 @@ extendedKeyUsage = serverAuth
35
35
  subjectAltName = @subject_alt_names
36
36
 
37
37
  [ subject_alt_names ]
38
- DNS.1 = <%= domain %>
39
- DNS.2 = *.<%= domain %>
38
+ DNS.1 = %DOMAIN%
39
+ DNS.2 = *.%DOMAIN%
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/devcert",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "Generate trusted local SSL/TLS certificates for local SSL development",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,26 +28,13 @@
28
28
  "homepage": "https://github.com/expo/devcert#readme",
29
29
  "devDependencies": {
30
30
  "@types/debug": "^0.0.30",
31
- "@types/get-port": "^3.2.0",
32
- "@types/lodash": "^4.14.92",
33
- "@types/mkdirp": "^0.5.2",
34
31
  "@types/node": "^20.12.7",
35
- "@types/tmp": "^0.0.33",
36
32
  "standard-version": "^8.0.1",
37
33
  "typescript": "^5.1.3"
38
34
  },
39
35
  "dependencies": {
40
- "application-config-path": "^0.1.0",
41
- "command-exists": "^1.2.4",
36
+ "@expo/sudo-prompt": "^9.3.1",
42
37
  "debug": "^3.1.0",
43
- "eol": "^0.9.1",
44
- "get-port": "^3.2.0",
45
- "glob": "^10.4.2",
46
- "lodash": "^4.17.21",
47
- "mkdirp": "^0.5.1",
48
- "password-prompt": "^1.0.4",
49
- "sudo-prompt": "^8.2.0",
50
- "tmp": "^0.0.33",
51
- "tslib": "^2.4.0"
38
+ "glob": "^10.4.2"
52
39
  }
53
40
  }
@@ -1,7 +1,6 @@
1
1
  // import path from 'path';
2
2
  import createDebug from 'debug';
3
- import { sync as mkdirp } from 'mkdirp';
4
- import { chmodSync as chmod } from 'fs';
3
+ import fs from 'fs';
5
4
  import { pathForDomain, withDomainSigningRequestConfig, withDomainCertificateConfig } from './constants';
6
5
  import { openssl } from './utils';
7
6
  import { withCertificateAuthorityCredentials } from './certificate-authority';
@@ -16,7 +15,7 @@ const debug = createDebug('devcert:certificates');
16
15
  * added to the OS/browser trust stores), they are trusted.
17
16
  */
18
17
  export default async function generateDomainCertificate(domain: string): Promise<void> {
19
- mkdirp(pathForDomain(domain));
18
+ await fs.promises.mkdir(pathForDomain(domain), { recursive: true });
20
19
 
21
20
  debug(`Generating private key for ${ domain }`);
22
21
  let domainKeyPath = pathForDomain(domain, 'private-key.key');
@@ -42,5 +41,5 @@ export default async function generateDomainCertificate(domain: string): Promise
42
41
  export function generateKey(filename: string): void {
43
42
  debug(`generateKey: ${ filename }`);
44
43
  openssl(['genrsa', '-out', filename, '2048']);
45
- chmod(filename, 400);
46
- }
44
+ fs.chmodSync(filename, 400);
45
+ }
package/src/constants.ts CHANGED
@@ -1,11 +1,23 @@
1
1
  import path from 'path';
2
- import { unlinkSync as rm, writeFileSync as writeFile, readFileSync as readFile } from 'fs';
3
- import { sync as mkdirp } from 'mkdirp';
4
- import { template as makeTemplate } from 'lodash';
5
- import applicationConfigPath = require('application-config-path');
6
- import eol from 'eol';
2
+ import fs from 'fs';
7
3
  import { mktmp } from './utils';
8
4
 
5
+ function applicationConfigPath(name: string): string {
6
+ switch (process.platform) {
7
+ case 'darwin':
8
+ return path.join(process.env.HOME, 'Library', 'Application Support', name);
9
+ case 'win32':
10
+ return process.env.LOCALAPPDATA
11
+ ? path.join(process.env.LOCALAPPDATA, name)
12
+ : path.join(process.env.USERPROFILE, 'Local Settings', 'Application Data', name);
13
+ case 'linux':
14
+ default:
15
+ return process.env.XDG_CONFIG_HOME
16
+ ? path.join(process.env.XDG_CONFIG_HOME, name)
17
+ : path.join(process.env.HOME, '.config', name);
18
+ }
19
+ }
20
+
9
21
  export const VALID_IP = /(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}/;
10
22
  export const VALID_DOMAIN = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.?)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/i;
11
23
 
@@ -26,34 +38,35 @@ export const opensslSerialFilePath = configPath('certificate-authority', 'serial
26
38
  export const opensslDatabaseFilePath = configPath('certificate-authority', 'index.txt');
27
39
  export const caSelfSignConfig = path.join(__dirname, '../openssl-configurations/certificate-authority-self-signing.conf');
28
40
 
41
+ function eolAuto(str: string): string {
42
+ return str.replace(/\r?\n|\r/g, isWindows ? '\r\n' : '\n');
43
+ }
44
+
29
45
  export function withDomainSigningRequestConfig(domain: string, cb: (filepath: string) => void) {
30
46
  let tmpFile = mktmp();
31
- let source = readFile(path.join(__dirname, '../openssl-configurations/domain-certificate-signing-requests.conf'), 'utf-8');
32
- let template = makeTemplate(source);
33
- let result = template({ domain });
34
- writeFile(tmpFile, eol.auto(result));
47
+ let source = fs.readFileSync(path.join(__dirname, '../openssl-configurations/domain-certificate-signing-requests.conf'), 'utf-8');
48
+ let result = source.replace(/%DOMAIN%/g, domain);
49
+ fs.writeFileSync(tmpFile, eolAuto(result));
35
50
  cb(tmpFile);
36
- rm(tmpFile);
51
+ fs.rmSync(tmpFile);
37
52
  }
38
53
 
39
54
  export function withDomainCertificateConfig(domain: string, cb: (filepath: string) => void) {
40
55
  let tmpFile = mktmp();
41
- let source = readFile(path.join(__dirname, '../openssl-configurations/domain-certificates.conf'), 'utf-8');
42
- let template = makeTemplate(source);
43
- let result = template({
44
- domain,
45
- serialFile: opensslSerialFilePath,
46
- databaseFile: opensslDatabaseFilePath,
47
- domainDir: pathForDomain(domain)
48
- });
49
- writeFile(tmpFile, eol.auto(result));
56
+ let source = fs.readFileSync(path.join(__dirname, '../openssl-configurations/domain-certificates.conf'), 'utf-8');
57
+ let result = source
58
+ .replace(/%DOMAIN%/g, domain)
59
+ .replace(/%SERIALFILE%/g, opensslSerialFilePath.replace(/\\/g, '\\\\'))
60
+ .replace(/%DATABASEFILE%/g, opensslDatabaseFilePath.replace(/\\/g, '\\\\'))
61
+ .replace(/%DOMAINDIR%/g, pathForDomain(domain).replace(/\\/g, '\\\\'))
62
+ fs.writeFileSync(tmpFile, eolAuto(result));
50
63
  cb(tmpFile);
51
- rm(tmpFile);
64
+ fs.rmSync(tmpFile);
52
65
  }
53
66
 
54
67
  // confTemplate = confTemplate.replace(/DATABASE_PATH/, configPath('index.txt').replace(/\\/g, '\\\\'));
55
68
  // confTemplate = confTemplate.replace(/SERIAL_PATH/, configPath('serial').replace(/\\/g, '\\\\'));
56
- // confTemplate = eol.auto(confTemplate);
69
+ // confTemplate = eolAuto(confTemplate);
57
70
 
58
71
  export const rootCADir = configPath('certificate-authority');
59
72
  export const rootCAKeyPath = configPath('certificate-authority', 'private-key.key');
@@ -73,9 +86,9 @@ export function getLegacyConfigDir(): string {
73
86
  }
74
87
 
75
88
  export function ensureConfigDirs() {
76
- mkdirp(configDir);
77
- mkdirp(domainsDir);
78
- mkdirp(rootCADir);
89
+ fs.mkdirSync(configDir, { recursive: true });
90
+ fs.mkdirSync(domainsDir, { recursive: true });
91
+ fs.mkdirSync(rootCADir, { recursive: true });
79
92
  }
80
93
 
81
94
  ensureConfigDirs();
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { rmSync as rm, readFileSync as readFile, readdirSync as readdir, existsSync as exists } from 'fs';
2
2
  import createDebug from 'debug';
3
- import { sync as commandExists } from 'command-exists';
4
3
  import {
5
4
  isMac,
6
5
  isLinux,
@@ -13,6 +12,7 @@ import {
13
12
  VALID_IP
14
13
  } from './constants';
15
14
  import currentPlatform from './platforms';
15
+ import { commandExists } from './utils';
16
16
  import installCertificateAuthority, { ensureCACertReadable, uninstall } from './certificate-authority';
17
17
  import generateDomainCertificate from './certificates';
18
18
  import UI, { UserInterface } from './user-interface';
@@ -1,8 +1,7 @@
1
1
  import path from 'path';
2
2
  import { writeFileSync as writeFile, existsSync as exists, readFileSync as read } from 'fs';
3
3
  import createDebug from 'debug';
4
- import { sync as commandExists } from 'command-exists';
5
- import { run, sudoAppend } from '../utils';
4
+ import { run, sudoAppend, commandExists } from '../utils';
6
5
  import { Options } from '../index';
7
6
  import { addCertificateToNSSCertDB, assertNotTouchingFiles, openCertificateInFirefox, closeFirefox, removeCertificateFromNSSCertDB } from './shared';
8
7
  import { Platform } from '.';
@@ -1,9 +1,8 @@
1
1
  import path from 'path';
2
2
  import { existsSync as exists, readFileSync as read, writeFileSync as writeFile } from 'fs';
3
3
  import createDebug from 'debug';
4
- import { sync as commandExists } from 'command-exists';
5
4
  import { addCertificateToNSSCertDB, assertNotTouchingFiles, openCertificateInFirefox, closeFirefox, removeCertificateFromNSSCertDB } from './shared';
6
- import { run, sudoAppend } from '../utils';
5
+ import { run, sudoAppend, commandExists } from '../utils';
7
6
  import { Options } from '../index';
8
7
  import UI from '../user-interface';
9
8
  import { Platform } from '.';
@@ -121,4 +120,4 @@ export default class LinuxPlatform implements Platform {
121
120
  return exists(this.CHROME_BIN_PATH);
122
121
  }
123
122
 
124
- }
123
+ }
@@ -1,8 +1,7 @@
1
1
  import path from 'path';
2
- import url from 'url';
3
2
  import createDebug from 'debug';
4
3
  import assert from 'assert';
5
- import getPort from 'get-port';
4
+ import net from 'net';
6
5
  import http from 'http';
7
6
  import { sync as glob } from 'glob';
8
7
  import { readFileSync as readFile, existsSync as exists } from 'fs';
@@ -109,28 +108,37 @@ async function sleep(ms: number) {
109
108
  */
110
109
  export async function openCertificateInFirefox(firefoxPath: string, certPath: string): Promise<void> {
111
110
  debug('Adding devert to Firefox trust stores manually. Launching a webserver to host our certificate temporarily ...');
112
- let port = await getPort();
113
- let server = http.createServer(async (req, res) => {
114
- let { pathname } = url.parse(req.url);
111
+ let port: number;
112
+ const server = http.createServer(async (req, res) => {
113
+ let { pathname } = new URL(req.url);
115
114
  if (pathname === '/certificate') {
116
115
  res.writeHead(200, { 'Content-type': 'application/x-x509-ca-cert' });
117
116
  res.write(readFile(certPath));
118
117
  res.end();
119
118
  } else {
120
119
  res.writeHead(200);
121
- res.write(await UI.firefoxWizardPromptPage(`http://localhost:${ port }/certificate`));
120
+ res.write(await UI.firefoxWizardPromptPage(`http://localhost:${port}/certificate`));
122
121
  res.end();
123
122
  }
124
- }).listen(port);
125
- debug('Certificate server is up. Printing instructions for user and launching Firefox with hosted certificate URL');
126
- await UI.startFirefoxWizard(`http://localhost:${ port }`);
127
- run(firefoxPath, [`http://localhost:${ port }`]);
128
- await UI.waitForFirefoxWizard();
129
- server.close();
123
+ });
124
+ port = await new Promise((resolve, reject) => {
125
+ server.on('error', reject);
126
+ server.listen(() => {
127
+ resolve((server.address() as net.AddressInfo).port);
128
+ });
129
+ });
130
+ try {
131
+ debug('Certificate server is up. Printing instructions for user and launching Firefox with hosted certificate URL');
132
+ await UI.startFirefoxWizard(`http://localhost:${port}`);
133
+ run(firefoxPath, [`http://localhost:${ port }`]);
134
+ await UI.waitForFirefoxWizard();
135
+ } finally {
136
+ server.close();
137
+ }
130
138
  }
131
139
 
132
140
  export function assertNotTouchingFiles(filepath: string, operation: string): void {
133
141
  if (!filepath.startsWith(configDir) && !filepath.startsWith(getLegacyConfigDir())) {
134
142
  throw new Error(`Devcert cannot ${ operation } ${ filepath }; it is outside known devcert config directories!`);
135
143
  }
136
- }
144
+ }
@@ -1,4 +1,4 @@
1
- import passwordPrompt from 'password-prompt';
1
+ import readline from 'node:readline';
2
2
  import { waitForUser } from './utils';
3
3
 
4
4
  export interface UserInterface {
@@ -10,6 +10,25 @@ export interface UserInterface {
10
10
  waitForFirefoxWizard(): Promise<void>;
11
11
  }
12
12
 
13
+ async function passwordPrompt(prompt: string): Promise<string> {
14
+ const input = readline.createInterface({
15
+ input: process.stdin,
16
+ output: process.stdout,
17
+ });
18
+ return new Promise((resolve, reject) => {
19
+ input.on('SIGINT', () => {
20
+ reject(new Error('SIGINT'));
21
+ });
22
+ input.question(prompt, (answer) => {
23
+ readline.moveCursor(process.stdout, 0, -1);
24
+ readline.clearLine(process.stdout, 0);
25
+ input.write(prompt + answer.replace(/./g, '*') + '\n');
26
+ input.close();
27
+ resolve(answer);
28
+ });
29
+ });
30
+ }
31
+
13
32
  const DefaultUI: UserInterface = {
14
33
  async getWindowsEncryptionPassword() {
15
34
  return await passwordPrompt('devcert password (http://bit.ly/devcert-what-password?):');
@@ -68,4 +87,4 @@ const DefaultUI: UserInterface = {
68
87
  }
69
88
  }
70
89
 
71
- export default DefaultUI;
90
+ export default DefaultUI;
package/src/utils.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { execFileSync, ExecFileSyncOptions } from 'child_process';
2
- import tmp from 'tmp';
2
+ import { randomBytes } from 'crypto';
3
+ import fs from 'fs';
4
+ import os from 'os';
3
5
  import createDebug from 'debug';
4
6
  import path from 'path';
5
- import sudoPrompt from 'sudo-prompt';
7
+ import sudoPrompt from '@expo/sudo-prompt';
6
8
 
7
- import { configPath } from './constants';
9
+ import { configPath, isWindows } from './constants';
8
10
 
9
11
  const debug = createDebug('devcert:util');
10
12
 
@@ -40,9 +42,10 @@ export function reportableError(message: string) {
40
42
  }
41
43
 
42
44
  export function mktmp() {
43
- // discardDescriptor because windows complains the file is in use if we create a tmp file
44
- // and then shell out to a process that tries to use it
45
- return tmp.fileSync({ discardDescriptor: true }).name;
45
+ const random = randomBytes(6).toString('hex');
46
+ const tmppath = path.join(os.tmpdir(), `tmp-${process.pid}${random}`);
47
+ fs.closeSync(fs.openSync(tmppath, 'w'));
48
+ return tmppath;
46
49
  }
47
50
 
48
51
  export function sudo(cmd: string): Promise<string | null> {
@@ -53,3 +56,23 @@ export function sudo(cmd: string): Promise<string | null> {
53
56
  });
54
57
  });
55
58
  }
59
+
60
+ const _commands: Record<string, string | null> = {};
61
+
62
+ export function commandExists(command: string): string | null {
63
+ if (_commands[command] !== undefined) {
64
+ return _commands[command];
65
+ }
66
+ const paths = process.env[isWindows ? 'Path' : 'PATH'].split(path.delimiter);
67
+ const extensions = [...(process.env.PATHEXT || '').split(path.delimiter), ''];
68
+ for (const dir of paths) {
69
+ for (const extension of extensions) {
70
+ const filePath = path.join(dir, command + extension);
71
+ try {
72
+ fs.accessSync(filePath, fs.constants.X_OK);
73
+ return (_commands[command] = filePath);
74
+ } catch {}
75
+ }
76
+ }
77
+ return (_commands[command] = null);
78
+ }
package/tsconfig.json CHANGED
@@ -4,10 +4,10 @@
4
4
  "declaration": true,
5
5
  "module": "commonjs",
6
6
  "moduleResolution": "node",
7
- "target": "ES2016",
7
+ "target": "ES2018",
8
8
  "noImplicitAny": true,
9
9
  "sourceMap": false,
10
- "importHelpers": true,
10
+ "importHelpers": false,
11
11
  "inlineSourceMap": true,
12
12
  "inlineSources": true,
13
13
  "outDir": "dist",
package/src/types.d.ts DELETED
@@ -1,7 +0,0 @@
1
- declare module "command-exists";
2
- declare module "eol";
3
- declare module "sudo-prompt";
4
- declare module "password-prompt";
5
- declare module "application-config-path" {
6
- export = (appName: string) => string;
7
- }