dominds 1.25.18 → 1.26.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 +17 -0
- package/README.zh.md +17 -0
- package/dist/apps/runtime.d.ts +2 -4
- package/dist/apps-host/client.d.ts +2 -5
- package/dist/apps-host/ipc-types.d.ts +2 -5
- package/dist/apps-host/ipc-types.js +5 -1
- package/dist/bootstrap/rtws-cli.d.ts +0 -1
- package/dist/bootstrap/rtws-cli.js +9 -3
- package/dist/cli/cert.d.ts +2 -0
- package/dist/cli/cert.js +198 -0
- package/dist/cli/create.d.ts +1 -1
- package/dist/cli/create.js +1 -1
- package/dist/cli/read.js +1 -1
- package/dist/cli/tui.js +1 -1
- package/dist/cli/webui.d.ts +1 -1
- package/dist/cli/webui.js +35 -5
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +21 -16
- package/dist/docs/cli-usage.md +43 -7
- package/dist/docs/cli-usage.zh.md +43 -7
- package/dist/docs/dialog-persistence.md +1 -1
- package/dist/docs/dominds-terminology.md +2 -2
- package/dist/server/auth.d.ts +7 -0
- package/dist/server/auth.js +15 -4
- package/dist/server/certificates.d.ts +61 -0
- package/dist/server/certificates.js +418 -0
- package/dist/server/dominds-self-update-restart-helper.d.ts +15 -0
- package/dist/server/dominds-self-update-restart-helper.js +305 -0
- package/dist/server/dominds-self-update.js +162 -120
- package/dist/server/network-hosts.d.ts +5 -0
- package/dist/server/network-hosts.js +188 -0
- package/dist/server/server-core.d.ts +12 -1
- package/dist/server/server-core.js +26 -4
- package/dist/server/websocket-handler.d.ts +3 -2
- package/dist/server/websocket-handler.js +15 -8
- package/dist/server.d.ts +5 -0
- package/dist/server.js +105 -10
- package/package.json +3 -3
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DEFAULT_SELF_SIGNED_CERT_DAYS = void 0;
|
|
37
|
+
exports.getDefaultDomindsCertsDir = getDefaultDomindsCertsDir;
|
|
38
|
+
exports.findAutoHttpsCertificateForHost = findAutoHttpsCertificateForHost;
|
|
39
|
+
exports.createSelfSignedCertificate = createSelfSignedCertificate;
|
|
40
|
+
const node_child_process_1 = require("node:child_process");
|
|
41
|
+
const node_crypto_1 = require("node:crypto");
|
|
42
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
43
|
+
const net = __importStar(require("node:net"));
|
|
44
|
+
const os = __importStar(require("node:os"));
|
|
45
|
+
const path = __importStar(require("node:path"));
|
|
46
|
+
const tls = __importStar(require("node:tls"));
|
|
47
|
+
const node_util_1 = require("node:util");
|
|
48
|
+
const network_hosts_1 = require("./network-hosts");
|
|
49
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
50
|
+
const CERT_EXTENSIONS = ['.crt', '.cert', '.pem'];
|
|
51
|
+
const KEY_SUFFIXES = ['.key.pem', '.key', '-key.pem'];
|
|
52
|
+
exports.DEFAULT_SELF_SIGNED_CERT_DAYS = 3650;
|
|
53
|
+
function getDefaultDomindsCertsDir() {
|
|
54
|
+
return path.join(os.homedir(), '.dominds', 'certs');
|
|
55
|
+
}
|
|
56
|
+
async function findAutoHttpsCertificateForHost(params) {
|
|
57
|
+
const host = (0, network_hosts_1.normalizeNetworkHost)(params.host);
|
|
58
|
+
const matchHosts = await (0, network_hosts_1.resolveLanHttpsHostsForBindHost)(host);
|
|
59
|
+
const endpoint = { bindHost: host, urlHost: matchHosts[0] ?? host };
|
|
60
|
+
const certsDirAbs = params.certsDirAbs ?? getDefaultDomindsCertsDir();
|
|
61
|
+
const now = params.now ?? new Date();
|
|
62
|
+
const diagnostics = [];
|
|
63
|
+
if (matchHosts.length === 0) {
|
|
64
|
+
return { kind: 'not_found', certsDirAbs, endpoint, diagnostics };
|
|
65
|
+
}
|
|
66
|
+
let entries;
|
|
67
|
+
try {
|
|
68
|
+
entries = await fs.readdir(certsDirAbs);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (isNodeErrorWithCode(error, 'ENOENT')) {
|
|
72
|
+
return { kind: 'not_found', certsDirAbs, endpoint, diagnostics };
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
const matches = [];
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
if (!isCertificateFilename(entry))
|
|
79
|
+
continue;
|
|
80
|
+
const certPath = path.join(certsDirAbs, entry);
|
|
81
|
+
const keyPath = await findKeyPathForCert({ certsDirAbs, certEntry: entry });
|
|
82
|
+
if (keyPath === null) {
|
|
83
|
+
diagnostics.push({
|
|
84
|
+
level: 'warn',
|
|
85
|
+
code: 'missing_key_file',
|
|
86
|
+
message: `Certificate has no matching private key: ${certPath}`,
|
|
87
|
+
certPath,
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const loaded = await loadAndValidateCandidate({
|
|
92
|
+
matchHosts,
|
|
93
|
+
now,
|
|
94
|
+
certPath,
|
|
95
|
+
keyPath,
|
|
96
|
+
});
|
|
97
|
+
if (loaded.kind === 'match') {
|
|
98
|
+
matches.push(loaded.certificate);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (loaded.kind === 'diagnostic') {
|
|
102
|
+
diagnostics.push(loaded.diagnostic);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (matches.length === 0) {
|
|
106
|
+
return { kind: 'not_found', certsDirAbs, endpoint, diagnostics };
|
|
107
|
+
}
|
|
108
|
+
matches.sort((a, b) => a.matchedHostPriority - b.matchedHostPriority || b.validTo.getTime() - a.validTo.getTime());
|
|
109
|
+
if (matches.length > 1) {
|
|
110
|
+
diagnostics.push({
|
|
111
|
+
level: 'warn',
|
|
112
|
+
code: 'multiple_matching_certs',
|
|
113
|
+
message: `Multiple valid certificates match host '${host}'; using the best-priority match with the latest expiry.`,
|
|
114
|
+
host,
|
|
115
|
+
certPaths: matches.map((m) => m.certPath),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
kind: 'found',
|
|
120
|
+
certsDirAbs,
|
|
121
|
+
endpoint: { bindHost: host, urlHost: matches[0].matchedHost },
|
|
122
|
+
certificate: matches[0],
|
|
123
|
+
diagnostics,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async function createSelfSignedCertificate(params) {
|
|
127
|
+
const hosts = normalizeCertificateHostsForCreate(params.host === undefined
|
|
128
|
+
? await (0, network_hosts_1.resolveDefaultLanHttpsHosts)()
|
|
129
|
+
: [params.host, ...(params.altHosts ?? [])], { skipInvalidHosts: params.host === undefined });
|
|
130
|
+
const host = hosts[0];
|
|
131
|
+
const days = normalizeDays(params.days ?? exports.DEFAULT_SELF_SIGNED_CERT_DAYS);
|
|
132
|
+
const certsDirAbs = params.certsDirAbs ?? getDefaultDomindsCertsDir();
|
|
133
|
+
const basename = certificateBasenameForHosts(hosts);
|
|
134
|
+
const certPath = path.join(certsDirAbs, `${basename}.crt.pem`);
|
|
135
|
+
const keyPath = path.join(certsDirAbs, `${basename}.key.pem`);
|
|
136
|
+
const metadataPath = path.join(certsDirAbs, `${basename}.json`);
|
|
137
|
+
await fs.mkdir(certsDirAbs, { recursive: true, mode: 0o700 });
|
|
138
|
+
if (params.force !== true) {
|
|
139
|
+
await assertPathDoesNotExist(certPath);
|
|
140
|
+
await assertPathDoesNotExist(keyPath);
|
|
141
|
+
await assertPathDoesNotExist(metadataPath);
|
|
142
|
+
}
|
|
143
|
+
const san = buildSubjectAltName(hosts);
|
|
144
|
+
await execFileAsync('openssl', [
|
|
145
|
+
'req',
|
|
146
|
+
'-x509',
|
|
147
|
+
'-newkey',
|
|
148
|
+
'rsa:2048',
|
|
149
|
+
'-sha256',
|
|
150
|
+
'-nodes',
|
|
151
|
+
'-days',
|
|
152
|
+
String(days),
|
|
153
|
+
'-keyout',
|
|
154
|
+
keyPath,
|
|
155
|
+
'-out',
|
|
156
|
+
certPath,
|
|
157
|
+
'-subj',
|
|
158
|
+
`/CN=${escapeOpenSslSubjectValue(host)}`,
|
|
159
|
+
'-addext',
|
|
160
|
+
`subjectAltName=${san}`,
|
|
161
|
+
], { maxBuffer: 1024 * 1024 });
|
|
162
|
+
await fs.chmod(keyPath, 0o600);
|
|
163
|
+
await fs.chmod(certPath, 0o644);
|
|
164
|
+
const metadata = {
|
|
165
|
+
kind: 'dominds_self_signed_cert',
|
|
166
|
+
host,
|
|
167
|
+
hosts,
|
|
168
|
+
days,
|
|
169
|
+
certPath,
|
|
170
|
+
keyPath,
|
|
171
|
+
createdAt: new Date().toISOString(),
|
|
172
|
+
subjectAltName: san,
|
|
173
|
+
};
|
|
174
|
+
await fs.writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, 'utf8');
|
|
175
|
+
await fs.chmod(metadataPath, 0o644);
|
|
176
|
+
return { host, hosts, days, certsDirAbs, certPath, keyPath, metadataPath };
|
|
177
|
+
}
|
|
178
|
+
function normalizeCertificateHostsForCreate(rawHosts, options) {
|
|
179
|
+
const hosts = [];
|
|
180
|
+
const seen = new Set();
|
|
181
|
+
for (const rawHost of rawHosts) {
|
|
182
|
+
const hostCandidates = getCertificateMatchHostsForCreateHost(rawHost);
|
|
183
|
+
for (const host of hostCandidates) {
|
|
184
|
+
const validation = validateCertificateHost(host);
|
|
185
|
+
if (validation.kind === 'invalid') {
|
|
186
|
+
if (options.skipInvalidHosts)
|
|
187
|
+
continue;
|
|
188
|
+
throw new Error(validation.message);
|
|
189
|
+
}
|
|
190
|
+
const key = host.toLowerCase();
|
|
191
|
+
if (seen.has(key))
|
|
192
|
+
continue;
|
|
193
|
+
seen.add(key);
|
|
194
|
+
hosts.push(host);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (hosts.length === 0) {
|
|
198
|
+
throw new Error(options.skipInvalidHosts
|
|
199
|
+
? 'No certificate-valid non-loopback LAN host was detected; provide --host explicitly'
|
|
200
|
+
: '--host must be provided at least once');
|
|
201
|
+
}
|
|
202
|
+
return hosts;
|
|
203
|
+
}
|
|
204
|
+
function getCertificateMatchHostsForCreateHost(rawHost) {
|
|
205
|
+
const host = (0, network_hosts_1.normalizeNetworkHost)(rawHost);
|
|
206
|
+
return [host];
|
|
207
|
+
}
|
|
208
|
+
function normalizeDays(days) {
|
|
209
|
+
if (!Number.isInteger(days) || days < 1 || days > 36500) {
|
|
210
|
+
throw new Error('--days must be an integer in [1, 36500]');
|
|
211
|
+
}
|
|
212
|
+
return days;
|
|
213
|
+
}
|
|
214
|
+
function validateCertificateHost(host) {
|
|
215
|
+
if (host === '') {
|
|
216
|
+
return { kind: 'invalid', message: '--host must not be empty' };
|
|
217
|
+
}
|
|
218
|
+
if (host.includes('/')) {
|
|
219
|
+
return {
|
|
220
|
+
kind: 'invalid',
|
|
221
|
+
message: '--host must be an exact DNS name or IP address; CIDR/IP ranges are not valid',
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (!(0, network_hosts_1.isLanHttpsHost)(host)) {
|
|
225
|
+
return {
|
|
226
|
+
kind: 'invalid',
|
|
227
|
+
message: '--host must not be localhost, loopback, 127.0.0.0/8, ::1, 0.0.0.0, or ::',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (net.isIP(host) !== 0)
|
|
231
|
+
return { kind: 'valid' };
|
|
232
|
+
if (!isValidDnsHost(host)) {
|
|
233
|
+
return {
|
|
234
|
+
kind: 'invalid',
|
|
235
|
+
message: '--host must be a DNS name, an IPv4 address, or an IPv6 address',
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { kind: 'valid' };
|
|
239
|
+
}
|
|
240
|
+
function isValidDnsHost(host) {
|
|
241
|
+
if (host.length > 253)
|
|
242
|
+
return false;
|
|
243
|
+
const trimmed = host.endsWith('.') ? host.slice(0, -1) : host;
|
|
244
|
+
if (trimmed === '')
|
|
245
|
+
return false;
|
|
246
|
+
const labels = trimmed.split('.');
|
|
247
|
+
for (const label of labels) {
|
|
248
|
+
if (label.length < 1 || label.length > 63)
|
|
249
|
+
return false;
|
|
250
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/.test(label))
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
async function assertPathDoesNotExist(filePathAbs) {
|
|
256
|
+
try {
|
|
257
|
+
await fs.access(filePathAbs);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
if (isNodeErrorWithCode(error, 'ENOENT'))
|
|
261
|
+
return;
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
throw new Error(`Refusing to overwrite existing certificate file: ${filePathAbs}`);
|
|
265
|
+
}
|
|
266
|
+
function certificateBasenameForHosts(hosts) {
|
|
267
|
+
const host = hosts[0];
|
|
268
|
+
const safeHost = host
|
|
269
|
+
.toLowerCase()
|
|
270
|
+
.replace(/[^a-z0-9.-]+/g, '_')
|
|
271
|
+
.replace(/^_+|_+$/g, '');
|
|
272
|
+
const digest = (0, node_crypto_1.createHash)('sha256').update(hosts.join('\0')).digest('hex').slice(0, 8);
|
|
273
|
+
return `dominds-${safeHost || 'host'}-${digest}`;
|
|
274
|
+
}
|
|
275
|
+
function buildSubjectAltName(hosts) {
|
|
276
|
+
return hosts
|
|
277
|
+
.map((host) => {
|
|
278
|
+
const ipVersion = net.isIP(host);
|
|
279
|
+
return ipVersion !== 0 ? `IP:${host}` : `DNS:${host}`;
|
|
280
|
+
})
|
|
281
|
+
.join(',');
|
|
282
|
+
}
|
|
283
|
+
function escapeOpenSslSubjectValue(value) {
|
|
284
|
+
return value.replace(/\\/g, '\\\\').replace(/\//g, '\\/');
|
|
285
|
+
}
|
|
286
|
+
function isCertificateFilename(filename) {
|
|
287
|
+
return CERT_EXTENSIONS.some((ext) => filename.endsWith(ext)) && !isKeyFilename(filename);
|
|
288
|
+
}
|
|
289
|
+
function isKeyFilename(filename) {
|
|
290
|
+
return KEY_SUFFIXES.some((suffix) => filename.endsWith(suffix));
|
|
291
|
+
}
|
|
292
|
+
async function findKeyPathForCert(params) {
|
|
293
|
+
const baseNames = certBaseNameVariants(params.certEntry);
|
|
294
|
+
for (const baseName of baseNames) {
|
|
295
|
+
for (const suffix of KEY_SUFFIXES) {
|
|
296
|
+
const keyPath = path.join(params.certsDirAbs, `${baseName}${suffix}`);
|
|
297
|
+
try {
|
|
298
|
+
await fs.access(keyPath);
|
|
299
|
+
return keyPath;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
if (isNodeErrorWithCode(error, 'ENOENT'))
|
|
303
|
+
continue;
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
function certBaseNameVariants(certEntry) {
|
|
311
|
+
const variants = [];
|
|
312
|
+
for (const ext of CERT_EXTENSIONS) {
|
|
313
|
+
if (certEntry.endsWith(ext)) {
|
|
314
|
+
variants.push(certEntry.slice(0, -ext.length));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (certEntry.endsWith('.crt.pem')) {
|
|
318
|
+
variants.push(certEntry.slice(0, -'.crt.pem'.length));
|
|
319
|
+
}
|
|
320
|
+
return Array.from(new Set(variants));
|
|
321
|
+
}
|
|
322
|
+
async function loadAndValidateCandidate(params) {
|
|
323
|
+
let certPem;
|
|
324
|
+
let keyPem;
|
|
325
|
+
let cert;
|
|
326
|
+
try {
|
|
327
|
+
certPem = await fs.readFile(params.certPath, 'utf8');
|
|
328
|
+
keyPem = await fs.readFile(params.keyPath, 'utf8');
|
|
329
|
+
cert = new node_crypto_1.X509Certificate(certPem);
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
return {
|
|
333
|
+
kind: 'diagnostic',
|
|
334
|
+
diagnostic: {
|
|
335
|
+
level: 'warn',
|
|
336
|
+
code: 'invalid_cert_file',
|
|
337
|
+
message: `Invalid certificate file '${params.certPath}': ${formatUnknownError(error)}`,
|
|
338
|
+
certPath: params.certPath,
|
|
339
|
+
keyPath: params.keyPath,
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
const matchedHost = findCertificateMatchedHost(cert, params.matchHosts);
|
|
344
|
+
if (matchedHost === null) {
|
|
345
|
+
return { kind: 'no_match' };
|
|
346
|
+
}
|
|
347
|
+
if (!certificateIsCurrentlyValid(cert, params.now)) {
|
|
348
|
+
return {
|
|
349
|
+
kind: 'diagnostic',
|
|
350
|
+
diagnostic: {
|
|
351
|
+
level: 'warn',
|
|
352
|
+
code: 'expired_or_not_yet_valid',
|
|
353
|
+
message: `Certificate is not currently valid: ${params.certPath}`,
|
|
354
|
+
certPath: params.certPath,
|
|
355
|
+
keyPath: params.keyPath,
|
|
356
|
+
},
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
tls.createSecureContext({ cert: certPem, key: keyPem });
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return {
|
|
364
|
+
kind: 'diagnostic',
|
|
365
|
+
diagnostic: {
|
|
366
|
+
level: 'warn',
|
|
367
|
+
code: 'invalid_key_pair',
|
|
368
|
+
message: `Certificate and private key do not form a valid TLS pair: ${formatUnknownError(error)}`,
|
|
369
|
+
certPath: params.certPath,
|
|
370
|
+
keyPath: params.keyPath,
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
return {
|
|
375
|
+
kind: 'match',
|
|
376
|
+
certificate: {
|
|
377
|
+
cert: certPem,
|
|
378
|
+
key: keyPem,
|
|
379
|
+
certPath: params.certPath,
|
|
380
|
+
keyPath: params.keyPath,
|
|
381
|
+
matchedHost: matchedHost.host,
|
|
382
|
+
matchedHostPriority: matchedHost.priority,
|
|
383
|
+
validTo: new Date(Date.parse(cert.validTo)),
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function certificateIsCurrentlyValid(cert, now) {
|
|
388
|
+
const validFromMs = Date.parse(cert.validFrom);
|
|
389
|
+
const validToMs = Date.parse(cert.validTo);
|
|
390
|
+
if (!Number.isFinite(validFromMs) || !Number.isFinite(validToMs)) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
const nowMs = now.getTime();
|
|
394
|
+
return validFromMs <= nowMs && nowMs <= validToMs;
|
|
395
|
+
}
|
|
396
|
+
function findCertificateMatchedHost(cert, matchHosts) {
|
|
397
|
+
for (let i = 0; i < matchHosts.length; i += 1) {
|
|
398
|
+
const host = matchHosts[i];
|
|
399
|
+
if (certificateMatchesHost(cert, host)) {
|
|
400
|
+
return { host, priority: i };
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
function certificateMatchesHost(cert, host) {
|
|
406
|
+
const normalizedHost = (0, network_hosts_1.normalizeNetworkHost)(host);
|
|
407
|
+
const ipVersion = net.isIP(normalizedHost);
|
|
408
|
+
if (ipVersion !== 0) {
|
|
409
|
+
return cert.checkIP(normalizedHost) !== undefined;
|
|
410
|
+
}
|
|
411
|
+
return cert.checkHost(normalizedHost) !== undefined;
|
|
412
|
+
}
|
|
413
|
+
function isNodeErrorWithCode(error, code) {
|
|
414
|
+
return error instanceof Error && error.code === code;
|
|
415
|
+
}
|
|
416
|
+
function formatUnknownError(error) {
|
|
417
|
+
return error instanceof Error ? error.message : String(error);
|
|
418
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type RestartHelperStdioMode = 'inherit' | 'ignore';
|
|
2
|
+
export type RestartHelperPayload = Readonly<{
|
|
3
|
+
command: string;
|
|
4
|
+
args: readonly string[];
|
|
5
|
+
cwd: string;
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
retiringPid: number;
|
|
9
|
+
forceKillAfterMs: number;
|
|
10
|
+
probeIntervalMs: number;
|
|
11
|
+
portReleaseTimeoutMs: number;
|
|
12
|
+
stdioMode: RestartHelperStdioMode;
|
|
13
|
+
traceFile: string;
|
|
14
|
+
debugDir: string;
|
|
15
|
+
}>;
|