-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
135 lines (108 loc) · 3.9 KB
/
index.js
File metadata and controls
135 lines (108 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import child_process from 'child_process';
import fs from 'fs';
import https from 'https';
import util from 'util';
/** @type {Record<string, string>}} */
const platforms = { win32: 'windows' };
/** @type {Record<string, string>}} */
const archs = { x64: 'amd64' };
export default async function* () {
yield 'read';
// Serve the certificates directly if they are already downloaded
try {
const key = await fs.promises.readFile('localhost-key.pem');
const cert = await fs.promises.readFile('localhost.pem');
yield { key, cert };
return;
}
catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
yield 'touch';
try {
await fs.promises.access('mkcert');
}
// Swallow error as we proceed to download mkcert
catch (error) {
yield 'version';
// Fetch the information of the latest `mkcert` version
const data = await new Promise((resolve, reject) => {
const request = https.get('https://api.github.com/repos/FiloSottile/mkcert/releases/latest', { headers: { 'User-Agent': '@tomashubelbauer' } }, async response => {
request.on('error', reject);
/** @type {Buffer[]} */
const buffers = [];
for await (const chunk of response) {
buffers.push(chunk);
}
const buffer = Buffer.concat(buffers);
resolve(JSON.parse(buffer.toString()));
});
});
const platform = platforms[process.platform] || process.platform;
const arch = archs[process.arch] || process.arch;
const name = platform + '-' + arch;
// Find the release asset for this platform and architecture using the `mkcert` naming convention
const asset = data.assets.find((/** @type {{ name: string; }} */ asset) => asset.name.endsWith(name));
// Fetch the download URL from the redirect page
yield 'redirect';
const text = await new Promise((resolve, reject) => {
const request = https.get(asset.browser_download_url, async response => {
request.on('error', reject);
/** @type {Buffer[]} */
const buffers = [];
for await (const chunk of response) {
buffers.push(chunk);
}
const buffer = Buffer.concat(buffers);
resolve(buffer.toString());
});
});
const regex = /^<html><body>You are being <a href="(?<url>.*)">redirected<\/a>.<\/body><\/html>$/g;
const match = regex.exec(text);
if (!match?.groups?.url) {
throw new Error('The redirect URL was not found in the response!');
}
const url = match.groups.url.replace(/&/g, '&');
// Download the executable binary
yield 'download';
const buffer = await new Promise((resolve, reject) => {
const request = https.get(url, async response => {
request.on('error', reject);
/** @type {Buffer[]} */
const buffers = [];
for await (const chunk of response) {
buffers.push(chunk);
}
const buffer = Buffer.concat(buffers);
resolve(buffer);
});
});
yield 'write';
await fs.promises.writeFile('mkcert', buffer);
}
// Make mkcert executable if it is not already (e.g. right after download)
if (process.platform !== 'win32') {
yield 'mod';
const mod = await util.promisify(child_process.exec)('chmod +x mkcert', { cwd: '.' });
if (mod.stderr) {
throw new Error(mod.stderr);
}
if (mod.stdout) {
throw new Error(mod.stdout);
}
}
// Run mkcert executable to obtain localhost certificates
yield 'run';
const run = await util.promisify(child_process.exec)('./mkcert localhost', { cwd: '.' });
if (!run.stderr.match(/The certificate is at ".\/localhost.pem" and the key at ".\/localhost-key.pem"/)) {
throw new Error(run.stderr);
}
if (run.stdout) {
throw new Error(run.stdout);
}
const key = await fs.promises.readFile('localhost-key.pem');
const cert = await fs.promises.readFile('localhost.pem');
yield { key, cert };
}