@jsenv/https-local 3.0.7 → 3.1.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.
- package/README.md +160 -192
- package/package.json +10 -30
- package/src/certificate_authority.js +111 -110
- package/src/certificate_request.js +34 -35
- package/src/hosts_file_verif.js +34 -35
- package/src/https_local_cli.mjs +74 -0
- package/src/internal/authority_file_infos.js +12 -13
- package/src/internal/browser_detection.js +4 -4
- package/src/internal/certificate_authority_file_urls.js +23 -23
- package/src/internal/certificate_data_converter.js +39 -39
- package/src/internal/certificate_generator.js +39 -39
- package/src/internal/command.js +6 -6
- package/src/internal/exec.js +10 -10
- package/src/internal/forge.js +3 -3
- package/src/internal/hosts/hosts_utils.js +2 -2
- package/src/internal/hosts/parse_hosts.js +67 -66
- package/src/internal/hosts/read_hosts.js +5 -6
- package/src/internal/hosts/write_hosts.js +29 -31
- package/src/internal/hosts/write_line_hosts.js +30 -32
- package/src/internal/hosts.js +5 -5
- package/src/internal/linux/chrome_linux.js +19 -20
- package/src/internal/linux/firefox_linux.js +19 -20
- package/src/internal/linux/linux.js +8 -8
- package/src/internal/linux/linux_trust_store.js +58 -59
- package/src/internal/linux/nss_linux.js +20 -21
- package/src/internal/mac/chrome_mac.js +15 -16
- package/src/internal/mac/firefox_mac.js +20 -21
- package/src/internal/mac/mac.js +10 -10
- package/src/internal/mac/mac_keychain.js +46 -47
- package/src/internal/mac/nss_mac.js +29 -30
- package/src/internal/mac/safari.js +2 -2
- package/src/internal/memoize.js +14 -14
- package/src/internal/nssdb_browser.js +150 -145
- package/src/internal/platform.js +6 -6
- package/src/internal/search_certificate_in_command_output.js +4 -4
- package/src/internal/trust_query.js +4 -4
- package/src/internal/unsupported_platform/unsupported_platform.js +5 -5
- package/src/internal/validity_formatting.js +32 -32
- package/src/internal/windows/chrome_windows.js +26 -27
- package/src/internal/windows/edge.js +2 -2
- package/src/internal/windows/firefox_windows.js +31 -32
- package/src/internal/windows/windows.js +10 -10
- package/src/internal/windows/windows_certutil.js +41 -42
- package/src/jsenvParameters.js +2 -2
- package/src/main.js +5 -8
- package/src/validity_duration.js +12 -12
package/src/internal/command.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createRequire } from "node:module"
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
2
|
|
|
3
|
-
const require = createRequire(import.meta.url)
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
4
|
|
|
5
5
|
export const commandExists = async (command) => {
|
|
6
|
-
const { sync } = require("command-exists")
|
|
7
|
-
const exists = sync(command)
|
|
8
|
-
return exists
|
|
9
|
-
}
|
|
6
|
+
const { sync } = require("command-exists");
|
|
7
|
+
const exists = sync(command);
|
|
8
|
+
return exists;
|
|
9
|
+
};
|
package/src/internal/exec.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { exec as nodeExec } from "node:child_process"
|
|
1
|
+
import { exec as nodeExec } from "node:child_process";
|
|
2
2
|
|
|
3
3
|
export const exec = (
|
|
4
4
|
command,
|
|
@@ -14,20 +14,20 @@ export const exec = (
|
|
|
14
14
|
},
|
|
15
15
|
(error, stdout) => {
|
|
16
16
|
if (error) {
|
|
17
|
-
reject(error)
|
|
17
|
+
reject(error);
|
|
18
18
|
} else {
|
|
19
|
-
resolve(stdout)
|
|
19
|
+
resolve(stdout);
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
-
)
|
|
22
|
+
);
|
|
23
23
|
|
|
24
24
|
commandProcess.stdout.on("data", (data) => {
|
|
25
|
-
onLog(data)
|
|
26
|
-
})
|
|
25
|
+
onLog(data);
|
|
26
|
+
});
|
|
27
27
|
commandProcess.stderr.on("data", (data) => {
|
|
28
28
|
// debug because this output is part of
|
|
29
29
|
// the error message generated by a failing npm publish
|
|
30
|
-
onErrorLog(data)
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
}
|
|
30
|
+
onErrorLog(data);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
};
|
package/src/internal/forge.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createRequire } from "node:module"
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
2
|
|
|
3
|
-
const require = createRequire(import.meta.url)
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
4
|
|
|
5
|
-
export const forge = require("node-forge")
|
|
5
|
+
export const forge = require("node-forge");
|
|
@@ -1,134 +1,135 @@
|
|
|
1
|
-
const IS_WINDOWS = process.platform === "win32"
|
|
1
|
+
const IS_WINDOWS = process.platform === "win32";
|
|
2
2
|
|
|
3
3
|
// https://github.com/feross/hostile/blob/master/index.js
|
|
4
4
|
export const parseHosts = (
|
|
5
5
|
hosts,
|
|
6
6
|
{ EOL = IS_WINDOWS ? "\r\n" : "\n" } = {},
|
|
7
7
|
) => {
|
|
8
|
-
const lines = []
|
|
8
|
+
const lines = [];
|
|
9
9
|
hosts.split(/\r?\n/).forEach((line) => {
|
|
10
|
-
const lineWithoutComments = line.replace(/#.*/, "")
|
|
11
|
-
|
|
10
|
+
const lineWithoutComments = line.replace(/#.*/, "");
|
|
11
|
+
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
12
|
+
const matches = /^\s*?(.+?)\s+(.+?)\s*$/.exec(lineWithoutComments);
|
|
12
13
|
if (matches && matches.length === 3) {
|
|
13
|
-
const [, ip, host] = matches
|
|
14
|
-
const hostnames = host.split(" ")
|
|
15
|
-
lines.push({ type: "rule", ip, hostnames })
|
|
14
|
+
const [, ip, host] = matches;
|
|
15
|
+
const hostnames = host.split(" ");
|
|
16
|
+
lines.push({ type: "rule", ip, hostnames });
|
|
16
17
|
} else {
|
|
17
18
|
// Found a comment, blank line, or something else
|
|
18
|
-
lines.push({ type: "other", value: line })
|
|
19
|
+
lines.push({ type: "other", value: line });
|
|
19
20
|
}
|
|
20
|
-
})
|
|
21
|
+
});
|
|
21
22
|
|
|
22
23
|
const getAllIpHostnames = () => {
|
|
23
|
-
const ipHostnames = {}
|
|
24
|
+
const ipHostnames = {};
|
|
24
25
|
lines.forEach((line) => {
|
|
25
26
|
if (line.type === "rule") {
|
|
26
|
-
const { ip, hostnames } = line
|
|
27
|
-
const existingHostnames = ipHostnames[ip]
|
|
27
|
+
const { ip, hostnames } = line;
|
|
28
|
+
const existingHostnames = ipHostnames[ip];
|
|
28
29
|
ipHostnames[ip] = existingHostnames
|
|
29
30
|
? [...existingHostnames, ...hostnames]
|
|
30
|
-
: hostnames
|
|
31
|
+
: hostnames;
|
|
31
32
|
}
|
|
32
|
-
})
|
|
33
|
-
return ipHostnames
|
|
34
|
-
}
|
|
33
|
+
});
|
|
34
|
+
return ipHostnames;
|
|
35
|
+
};
|
|
35
36
|
|
|
36
37
|
const getIpHostnames = (ip) => {
|
|
37
|
-
const hosts = []
|
|
38
|
+
const hosts = [];
|
|
38
39
|
lines.forEach((line) => {
|
|
39
40
|
if (line.type === "rule" && line.ip === ip) {
|
|
40
|
-
hosts.push(...line.hostnames)
|
|
41
|
+
hosts.push(...line.hostnames);
|
|
41
42
|
}
|
|
42
|
-
})
|
|
43
|
-
return hosts
|
|
44
|
-
}
|
|
43
|
+
});
|
|
44
|
+
return hosts;
|
|
45
|
+
};
|
|
45
46
|
|
|
46
47
|
const addIpHostname = (ip, host) => {
|
|
47
48
|
const alreadyThere = lines.some(
|
|
48
49
|
(line) =>
|
|
49
50
|
line.type === "rule" && line.ip === ip && line.hostnames.includes(host),
|
|
50
|
-
)
|
|
51
|
+
);
|
|
51
52
|
if (alreadyThere) {
|
|
52
|
-
return false
|
|
53
|
+
return false;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
const rule = { type: "rule", ip, hostnames: [host] }
|
|
56
|
-
const lastLineIndex = lines.length - 1
|
|
57
|
-
const lastLine = lines[lastLineIndex]
|
|
56
|
+
const rule = { type: "rule", ip, hostnames: [host] };
|
|
57
|
+
const lastLineIndex = lines.length - 1;
|
|
58
|
+
const lastLine = lines[lastLineIndex];
|
|
58
59
|
// last line is just empty characters, put the rule above it
|
|
59
60
|
if (lastLine.type === "other" && /\s*/.test(lastLine.value)) {
|
|
60
|
-
lines.splice(lastLineIndex, 0, rule)
|
|
61
|
+
lines.splice(lastLineIndex, 0, rule);
|
|
61
62
|
} else {
|
|
62
|
-
lines.push(rule)
|
|
63
|
+
lines.push(rule);
|
|
63
64
|
}
|
|
64
|
-
return true
|
|
65
|
-
}
|
|
65
|
+
return true;
|
|
66
|
+
};
|
|
66
67
|
|
|
67
68
|
const removeIpHostname = (ip, host) => {
|
|
68
|
-
let lineIndexFound
|
|
69
|
-
let hostnamesFound
|
|
70
|
-
let hostIndexFound
|
|
69
|
+
let lineIndexFound;
|
|
70
|
+
let hostnamesFound;
|
|
71
|
+
let hostIndexFound;
|
|
71
72
|
const found = lines.find((line, lineIndex) => {
|
|
72
73
|
if (line.type !== "rule") {
|
|
73
|
-
return false
|
|
74
|
+
return false;
|
|
74
75
|
}
|
|
75
76
|
if (line.ip !== ip) {
|
|
76
|
-
return false
|
|
77
|
+
return false;
|
|
77
78
|
}
|
|
78
|
-
const { hostnames } = line
|
|
79
|
-
const hostIndex = hostnames.indexOf(host)
|
|
79
|
+
const { hostnames } = line;
|
|
80
|
+
const hostIndex = hostnames.indexOf(host);
|
|
80
81
|
if (hostIndex === -1) {
|
|
81
|
-
return false
|
|
82
|
+
return false;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
lineIndexFound = lineIndex
|
|
85
|
-
hostnamesFound = hostnames
|
|
86
|
-
hostIndexFound = hostIndex
|
|
87
|
-
return true
|
|
88
|
-
})
|
|
85
|
+
lineIndexFound = lineIndex;
|
|
86
|
+
hostnamesFound = hostnames;
|
|
87
|
+
hostIndexFound = hostIndex;
|
|
88
|
+
return true;
|
|
89
|
+
});
|
|
89
90
|
|
|
90
91
|
if (!found) {
|
|
91
|
-
return false
|
|
92
|
+
return false;
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
if (hostnamesFound.length === 1) {
|
|
95
|
-
lines.splice(lineIndexFound, 1)
|
|
96
|
-
return true
|
|
96
|
+
lines.splice(lineIndexFound, 1);
|
|
97
|
+
return true;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
hostnamesFound.splice(hostIndexFound, 1)
|
|
100
|
-
return true
|
|
101
|
-
}
|
|
100
|
+
hostnamesFound.splice(hostIndexFound, 1);
|
|
101
|
+
return true;
|
|
102
|
+
};
|
|
102
103
|
|
|
103
104
|
const asFileContent = () => {
|
|
104
|
-
let hostsFileContent = ""
|
|
105
|
+
let hostsFileContent = "";
|
|
105
106
|
const ips = lines
|
|
106
107
|
.filter((line) => line.type === "rule")
|
|
107
|
-
.map((line) => line.ip)
|
|
108
|
+
.map((line) => line.ip);
|
|
108
109
|
const longestIp = ips.reduce((previous, ip) => {
|
|
109
|
-
const length = ip.length
|
|
110
|
-
return length > previous ? length : previous
|
|
111
|
-
}, 0)
|
|
110
|
+
const length = ip.length;
|
|
111
|
+
return length > previous ? length : previous;
|
|
112
|
+
}, 0);
|
|
112
113
|
|
|
113
114
|
lines.forEach((line, index) => {
|
|
114
115
|
if (line.type === "rule") {
|
|
115
|
-
const { ip, hostnames } = line
|
|
116
|
-
const ipLength = ip.length
|
|
117
|
-
const lengthDelta = longestIp - ipLength
|
|
116
|
+
const { ip, hostnames } = line;
|
|
117
|
+
const ipLength = ip.length;
|
|
118
|
+
const lengthDelta = longestIp - ipLength;
|
|
118
119
|
hostsFileContent += `${ip}${" ".repeat(lengthDelta)} ${hostnames.join(
|
|
119
120
|
" ",
|
|
120
|
-
)}
|
|
121
|
+
)}`;
|
|
121
122
|
} else {
|
|
122
|
-
hostsFileContent += line.value
|
|
123
|
+
hostsFileContent += line.value;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
const nextLine = lines[index + 1]
|
|
126
|
+
const nextLine = lines[index + 1];
|
|
126
127
|
if (nextLine) {
|
|
127
|
-
hostsFileContent += EOL
|
|
128
|
+
hostsFileContent += EOL;
|
|
128
129
|
}
|
|
129
|
-
})
|
|
130
|
-
return hostsFileContent
|
|
131
|
-
}
|
|
130
|
+
});
|
|
131
|
+
return hostsFileContent;
|
|
132
|
+
};
|
|
132
133
|
|
|
133
134
|
return {
|
|
134
135
|
getAllIpHostnames,
|
|
@@ -136,5 +137,5 @@ export const parseHosts = (
|
|
|
136
137
|
addIpHostname,
|
|
137
138
|
removeIpHostname,
|
|
138
139
|
asFileContent,
|
|
139
|
-
}
|
|
140
|
-
}
|
|
140
|
+
};
|
|
141
|
+
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { readFile } from "@jsenv/filesystem"
|
|
2
|
-
|
|
3
|
-
import { HOSTS_FILE_PATH } from "./hosts_utils.js"
|
|
1
|
+
import { readFile } from "@jsenv/filesystem";
|
|
2
|
+
import { HOSTS_FILE_PATH } from "./hosts_utils.js";
|
|
4
3
|
|
|
5
4
|
export const readHostsFile = async (hostsFilePath = HOSTS_FILE_PATH) => {
|
|
6
|
-
const hostsFileContent = await readFile(hostsFilePath, { as: "string" })
|
|
7
|
-
return hostsFileContent
|
|
8
|
-
}
|
|
5
|
+
const hostsFileContent = await readFile(hostsFilePath, { as: "string" });
|
|
6
|
+
return hostsFileContent;
|
|
7
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { createRequire } from "node:module"
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { HOSTS_FILE_PATH } from "./hosts_utils.js"
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { exec } from "../exec.js";
|
|
3
|
+
import { HOSTS_FILE_PATH } from "./hosts_utils.js";
|
|
6
4
|
|
|
7
5
|
export const writeHostsFile = async (
|
|
8
6
|
hostsFileContent,
|
|
@@ -13,71 +11,71 @@ export const writeHostsFile = async (
|
|
|
13
11
|
hostsFileContent,
|
|
14
12
|
hostsFilePath,
|
|
15
13
|
onBeforeExecCommand,
|
|
16
|
-
})
|
|
14
|
+
});
|
|
17
15
|
}
|
|
18
16
|
return writeHostsFileOnLinuxOrMac({
|
|
19
17
|
hostsFileContent,
|
|
20
18
|
hostsFilePath,
|
|
21
19
|
onBeforeExecCommand,
|
|
22
|
-
})
|
|
23
|
-
}
|
|
20
|
+
});
|
|
21
|
+
};
|
|
24
22
|
|
|
25
23
|
const writeHostsFileOnLinuxOrMac = async ({
|
|
26
24
|
hostsFilePath,
|
|
27
25
|
hostsFileContent,
|
|
28
26
|
onBeforeExecCommand,
|
|
29
27
|
}) => {
|
|
30
|
-
const needsSudo = hostsFilePath === HOSTS_FILE_PATH
|
|
28
|
+
const needsSudo = hostsFilePath === HOSTS_FILE_PATH;
|
|
31
29
|
// https://en.wikipedia.org/wiki/Tee_(command)
|
|
32
30
|
const updateHostsFileCommand = needsSudo
|
|
33
31
|
? `echo "${hostsFileContent}" | sudo tee ${hostsFilePath}`
|
|
34
|
-
: `echo "${hostsFileContent}" | tee ${hostsFilePath}
|
|
35
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
36
|
-
await exec(updateHostsFileCommand)
|
|
37
|
-
}
|
|
32
|
+
: `echo "${hostsFileContent}" | tee ${hostsFilePath}`;
|
|
33
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
34
|
+
await exec(updateHostsFileCommand);
|
|
35
|
+
};
|
|
38
36
|
|
|
39
37
|
const writeHostsFileOnWindows = async ({
|
|
40
38
|
hostsFilePath,
|
|
41
39
|
hostsFileContent,
|
|
42
40
|
onBeforeExecCommand,
|
|
43
41
|
}) => {
|
|
44
|
-
const needsSudo = hostsFilePath === HOSTS_FILE_PATH
|
|
45
|
-
const echoCommand = echoWithLinesToSingleCommand(hostsFileContent)
|
|
46
|
-
const updateHostsFileCommand = `${echoCommand} > ${hostsFilePath}
|
|
42
|
+
const needsSudo = hostsFilePath === HOSTS_FILE_PATH;
|
|
43
|
+
const echoCommand = echoWithLinesToSingleCommand(hostsFileContent);
|
|
44
|
+
const updateHostsFileCommand = `${echoCommand} > ${hostsFilePath}`;
|
|
47
45
|
|
|
48
46
|
if (needsSudo) {
|
|
49
|
-
const require = createRequire(import.meta.url)
|
|
50
|
-
const sudoPrompt = require("sudo-prompt")
|
|
51
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
47
|
+
const require = createRequire(import.meta.url);
|
|
48
|
+
const sudoPrompt = require("sudo-prompt");
|
|
49
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
52
50
|
await new Promise((resolve, reject) => {
|
|
53
51
|
sudoPrompt.exec(
|
|
54
52
|
updateHostsFileCommand,
|
|
55
53
|
{ name: "write hosts" },
|
|
56
54
|
(error, stdout, stderr) => {
|
|
57
55
|
if (error) {
|
|
58
|
-
reject(error)
|
|
56
|
+
reject(error);
|
|
59
57
|
} else if (typeof stderr === "string" && stderr.trim().length > 0) {
|
|
60
|
-
reject(stderr)
|
|
58
|
+
reject(stderr);
|
|
61
59
|
} else {
|
|
62
|
-
resolve(stdout)
|
|
60
|
+
resolve(stdout);
|
|
63
61
|
}
|
|
64
62
|
},
|
|
65
|
-
)
|
|
66
|
-
})
|
|
67
|
-
return
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
71
|
-
await exec(updateHostsFileCommand)
|
|
72
|
-
}
|
|
68
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
69
|
+
await exec(updateHostsFileCommand);
|
|
70
|
+
};
|
|
73
71
|
|
|
74
72
|
const echoWithLinesToSingleCommand = (value) => {
|
|
75
73
|
const command = value
|
|
76
74
|
.split(/\r\n/g)
|
|
77
75
|
.map((value) => `echo ${value}`)
|
|
78
|
-
.join(`& `)
|
|
79
|
-
return `(${command})
|
|
80
|
-
}
|
|
76
|
+
.join(`& `);
|
|
77
|
+
return `(${command})`;
|
|
78
|
+
};
|
|
81
79
|
|
|
82
80
|
// https://github.com/xxorax/node-shell-escape
|
|
83
81
|
// https://github.com/nodejs/node/issues/34840#issuecomment-677402567
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { HOSTS_FILE_PATH } from "./hosts_utils.js"
|
|
1
|
+
import { readFile } from "@jsenv/filesystem";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { exec } from "../exec.js";
|
|
4
|
+
import { HOSTS_FILE_PATH } from "./hosts_utils.js";
|
|
7
5
|
|
|
8
6
|
export const writeLineInHostsFile = async (
|
|
9
7
|
lineToAppend,
|
|
@@ -14,14 +12,14 @@ export const writeLineInHostsFile = async (
|
|
|
14
12
|
lineToAppend,
|
|
15
13
|
hostsFilePath,
|
|
16
14
|
onBeforeExecCommand,
|
|
17
|
-
})
|
|
15
|
+
});
|
|
18
16
|
}
|
|
19
17
|
return appendToHostsFileOnLinuxOrMac({
|
|
20
18
|
lineToAppend,
|
|
21
19
|
hostsFilePath,
|
|
22
20
|
onBeforeExecCommand,
|
|
23
|
-
})
|
|
24
|
-
}
|
|
21
|
+
});
|
|
22
|
+
};
|
|
25
23
|
|
|
26
24
|
// https://renenyffenegger.ch/notes/Windows/dirs/Windows/System32/cmd_exe/commands/echo/index
|
|
27
25
|
const appendToHostsFileOnWindows = async ({
|
|
@@ -29,55 +27,55 @@ const appendToHostsFileOnWindows = async ({
|
|
|
29
27
|
hostsFilePath,
|
|
30
28
|
onBeforeExecCommand,
|
|
31
29
|
}) => {
|
|
32
|
-
const hostsFileContent = await readFile(hostsFilePath, { as: "string" })
|
|
30
|
+
const hostsFileContent = await readFile(hostsFilePath, { as: "string" });
|
|
33
31
|
const echoCommand =
|
|
34
32
|
hostsFileContent.length > 0 && !hostsFileContent.endsWith("\r\n")
|
|
35
33
|
? `(echo.& echo ${lineToAppend})`
|
|
36
|
-
: `(echo ${lineToAppend})
|
|
37
|
-
const needsSudo = hostsFilePath === HOSTS_FILE_PATH
|
|
38
|
-
const updateHostsFileCommand = `${echoCommand} >> ${hostsFilePath}
|
|
34
|
+
: `(echo ${lineToAppend})`;
|
|
35
|
+
const needsSudo = hostsFilePath === HOSTS_FILE_PATH;
|
|
36
|
+
const updateHostsFileCommand = `${echoCommand} >> ${hostsFilePath}`;
|
|
39
37
|
|
|
40
38
|
if (needsSudo) {
|
|
41
|
-
const require = createRequire(import.meta.url)
|
|
42
|
-
const sudoPrompt = require("sudo-prompt")
|
|
43
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
39
|
+
const require = createRequire(import.meta.url);
|
|
40
|
+
const sudoPrompt = require("sudo-prompt");
|
|
41
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
44
42
|
await new Promise((resolve, reject) => {
|
|
45
43
|
sudoPrompt.exec(
|
|
46
44
|
updateHostsFileCommand,
|
|
47
45
|
{ name: "append hosts" },
|
|
48
46
|
(error, stdout, stderr) => {
|
|
49
47
|
if (error) {
|
|
50
|
-
reject(error)
|
|
48
|
+
reject(error);
|
|
51
49
|
} else if (typeof stderr === "string" && stderr.trim().length > 0) {
|
|
52
|
-
reject(stderr)
|
|
50
|
+
reject(stderr);
|
|
53
51
|
} else {
|
|
54
|
-
resolve(stdout)
|
|
52
|
+
resolve(stdout);
|
|
55
53
|
}
|
|
56
54
|
},
|
|
57
|
-
)
|
|
58
|
-
})
|
|
59
|
-
return
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
63
|
-
await exec(updateHostsFileCommand)
|
|
64
|
-
}
|
|
60
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
61
|
+
await exec(updateHostsFileCommand);
|
|
62
|
+
};
|
|
65
63
|
|
|
66
64
|
const appendToHostsFileOnLinuxOrMac = async ({
|
|
67
65
|
lineToAppend,
|
|
68
66
|
hostsFilePath,
|
|
69
67
|
onBeforeExecCommand,
|
|
70
68
|
}) => {
|
|
71
|
-
const hostsFileContent = await readFile(hostsFilePath, { as: "string" })
|
|
69
|
+
const hostsFileContent = await readFile(hostsFilePath, { as: "string" });
|
|
72
70
|
const echoCommand =
|
|
73
71
|
hostsFileContent.length > 0 && !hostsFileContent.endsWith("\n")
|
|
74
72
|
? `echo "\n${lineToAppend}"`
|
|
75
|
-
: `echo "${lineToAppend}"
|
|
76
|
-
const needsSudo = hostsFilePath === HOSTS_FILE_PATH
|
|
73
|
+
: `echo "${lineToAppend}"`;
|
|
74
|
+
const needsSudo = hostsFilePath === HOSTS_FILE_PATH;
|
|
77
75
|
// https://en.wikipedia.org/wiki/Tee_(command)
|
|
78
76
|
const updateHostsFileCommand = needsSudo
|
|
79
77
|
? `${echoCommand} | sudo tee -a ${hostsFilePath}`
|
|
80
|
-
: `${echoCommand} | tee -a ${hostsFilePath}
|
|
81
|
-
onBeforeExecCommand(updateHostsFileCommand)
|
|
82
|
-
await exec(updateHostsFileCommand)
|
|
83
|
-
}
|
|
78
|
+
: `${echoCommand} | tee -a ${hostsFilePath}`;
|
|
79
|
+
onBeforeExecCommand(updateHostsFileCommand);
|
|
80
|
+
await exec(updateHostsFileCommand);
|
|
81
|
+
};
|
package/src/internal/hosts.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { HOSTS_FILE_PATH } from "./hosts/hosts_utils.js"
|
|
1
|
+
export { HOSTS_FILE_PATH } from "./hosts/hosts_utils.js";
|
|
2
2
|
|
|
3
|
-
export { readHostsFile } from "./hosts/read_hosts.js"
|
|
3
|
+
export { readHostsFile } from "./hosts/read_hosts.js";
|
|
4
4
|
|
|
5
|
-
export { parseHosts } from "./hosts/parse_hosts.js"
|
|
5
|
+
export { parseHosts } from "./hosts/parse_hosts.js";
|
|
6
6
|
|
|
7
|
-
export { writeHostsFile } from "./hosts/write_hosts.js"
|
|
7
|
+
export { writeHostsFile } from "./hosts/write_hosts.js";
|
|
8
8
|
|
|
9
|
-
export { writeLineInHostsFile } from "./hosts/write_line_hosts.js"
|
|
9
|
+
export { writeLineInHostsFile } from "./hosts/write_line_hosts.js";
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js"
|
|
1
|
+
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
|
|
2
|
+
import { UNICODE } from "@jsenv/humanize";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js";
|
|
6
5
|
import {
|
|
7
|
-
nssCommandName,
|
|
8
6
|
detectIfNSSIsInstalled,
|
|
9
|
-
getNSSDynamicInstallInfo,
|
|
10
7
|
getCertutilBinPath,
|
|
11
|
-
|
|
8
|
+
getNSSDynamicInstallInfo,
|
|
9
|
+
nssCommandName,
|
|
10
|
+
} from "./nss_linux.js";
|
|
12
11
|
|
|
13
12
|
export const executeTrustQueryOnChrome = ({
|
|
14
13
|
logger,
|
|
@@ -47,29 +46,29 @@ export const executeTrustQueryOnChrome = ({
|
|
|
47
46
|
],
|
|
48
47
|
getBrowserClosedPromise: async () => {
|
|
49
48
|
if (!isChromeOpen()) {
|
|
50
|
-
return
|
|
49
|
+
return;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
logger.warn(
|
|
54
53
|
`${UNICODE.WARNING} waiting for you to close Chrome before resuming...`,
|
|
55
|
-
)
|
|
54
|
+
);
|
|
56
55
|
const next = async () => {
|
|
57
|
-
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
56
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
58
57
|
if (isChromeOpen()) {
|
|
59
|
-
await next()
|
|
58
|
+
await next();
|
|
60
59
|
} else {
|
|
61
|
-
logger.info(`${UNICODE.OK} Chrome closed, resuming`)
|
|
60
|
+
logger.info(`${UNICODE.OK} Chrome closed, resuming`);
|
|
62
61
|
// wait 50ms more to ensure chrome has time to cleanup
|
|
63
62
|
// othrwise sometimes there is an SEC_ERROR_REUSED_ISSUER_AND_SERIAL error
|
|
64
63
|
// because we updated nss database file while chrome is not fully closed
|
|
65
|
-
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
66
65
|
}
|
|
67
|
-
}
|
|
68
|
-
await next()
|
|
66
|
+
};
|
|
67
|
+
await next();
|
|
69
68
|
},
|
|
70
|
-
})
|
|
71
|
-
}
|
|
69
|
+
});
|
|
70
|
+
};
|
|
72
71
|
|
|
73
72
|
const isChromeOpen = () => {
|
|
74
|
-
return execSync("ps aux").includes("google chrome")
|
|
75
|
-
}
|
|
73
|
+
return execSync("ps aux").includes("google chrome");
|
|
74
|
+
};
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js"
|
|
1
|
+
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
|
|
2
|
+
import { UNICODE } from "@jsenv/humanize";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { executeTrustQueryOnBrowserNSSDB } from "../nssdb_browser.js";
|
|
6
5
|
import {
|
|
7
|
-
nssCommandName,
|
|
8
6
|
detectIfNSSIsInstalled,
|
|
9
|
-
getNSSDynamicInstallInfo,
|
|
10
7
|
getCertutilBinPath,
|
|
11
|
-
|
|
8
|
+
getNSSDynamicInstallInfo,
|
|
9
|
+
nssCommandName,
|
|
10
|
+
} from "./nss_linux.js";
|
|
12
11
|
|
|
13
12
|
export const executeTrustQueryOnFirefox = ({
|
|
14
13
|
logger,
|
|
@@ -56,29 +55,29 @@ export const executeTrustQueryOnFirefox = ({
|
|
|
56
55
|
],
|
|
57
56
|
getBrowserClosedPromise: async () => {
|
|
58
57
|
if (!isFirefoxOpen()) {
|
|
59
|
-
return
|
|
58
|
+
return;
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
logger.warn(
|
|
63
62
|
`${UNICODE.WARNING} waiting for you to close Firefox before resuming...`,
|
|
64
|
-
)
|
|
63
|
+
);
|
|
65
64
|
const next = async () => {
|
|
66
|
-
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
67
66
|
if (isFirefoxOpen()) {
|
|
68
|
-
await next()
|
|
67
|
+
await next();
|
|
69
68
|
} else {
|
|
70
|
-
logger.info(`${UNICODE.OK} Firefox closed, resuming`)
|
|
69
|
+
logger.info(`${UNICODE.OK} Firefox closed, resuming`);
|
|
71
70
|
// wait 50ms more to ensure firefox has time to cleanup
|
|
72
71
|
// othrwise sometimes there is an SEC_ERROR_REUSED_ISSUER_AND_SERIAL error
|
|
73
72
|
// because we updated nss database file while firefox is not fully closed
|
|
74
|
-
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
75
74
|
}
|
|
76
|
-
}
|
|
77
|
-
await next()
|
|
75
|
+
};
|
|
76
|
+
await next();
|
|
78
77
|
},
|
|
79
|
-
})
|
|
80
|
-
}
|
|
78
|
+
});
|
|
79
|
+
};
|
|
81
80
|
|
|
82
81
|
const isFirefoxOpen = () => {
|
|
83
|
-
return execSync("ps aux").includes("firefox")
|
|
84
|
-
}
|
|
82
|
+
return execSync("ps aux").includes("firefox");
|
|
83
|
+
};
|