1 | import { readFileSync as readFile, readdirSync as readdir, existsSync as exists } from 'fs';
|
2 | import createDebug from 'debug';
|
3 | import { sync as commandExists } from 'command-exists';
|
4 | import rimraf from 'rimraf';
|
5 | import {
|
6 | isMac,
|
7 | isLinux,
|
8 | isWindows,
|
9 | pathForDomain,
|
10 | domainsDir,
|
11 | rootCAKeyPath
|
12 | } from './constants';
|
13 | import currentPlatform from './platforms';
|
14 | import installCertificateAuthority from './certificate-authority';
|
15 | import generateDomainCertificate from './certificates';
|
16 | import UI, { UserInterface } from './user-interface';
|
17 |
|
18 | const debug = createDebug('devcert');
|
19 |
|
20 | export interface Options {
|
21 | skipCertutilInstall?: true,
|
22 | skipHostsFile?: true,
|
23 | ui?: UserInterface
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | export async function certificateFor(domain: string, options: Options = {}) {
|
39 | debug(`Certificate requested for ${ domain }. Skipping certutil install: ${ Boolean(options.skipCertutilInstall) }. Skipping hosts file: ${ Boolean(options.skipHostsFile) }`);
|
40 |
|
41 | if (options.ui) {
|
42 | Object.assign(UI, options.ui);
|
43 | }
|
44 |
|
45 | if (!isMac && !isLinux && !isWindows) {
|
46 | throw new Error(`Platform not supported: "${ process.platform }"`);
|
47 | }
|
48 |
|
49 | if (!commandExists('openssl')) {
|
50 | throw new Error('OpenSSL not found: OpenSSL is required to generate SSL certificates - make sure it is installed and available in your PATH');
|
51 | }
|
52 |
|
53 | let domainKeyPath = pathForDomain(domain, `private-key.key`);
|
54 | let domainCertPath = pathForDomain(domain, `certificate.crt`);
|
55 |
|
56 | if (!exists(rootCAKeyPath)) {
|
57 | debug('Root CA is not installed yet, so it must be our first run. Installing root CA ...');
|
58 | await installCertificateAuthority(options);
|
59 | }
|
60 |
|
61 | if (!exists(pathForDomain(domain, `certificate.crt`))) {
|
62 | debug(`Can't find certificate file for ${ domain }, so it must be the first request for ${ domain }. Generating and caching ...`);
|
63 | await generateDomainCertificate(domain);
|
64 | }
|
65 |
|
66 | if (!options.skipHostsFile) {
|
67 | await currentPlatform.addDomainToHostFileIfMissing(domain);
|
68 | }
|
69 |
|
70 | debug(`Returning domain certificate`);
|
71 | return {
|
72 | key: readFile(domainKeyPath),
|
73 | cert: readFile(domainCertPath)
|
74 | };
|
75 | }
|
76 |
|
77 | export function hasCertificateFor(domain: string) {
|
78 | return exists(pathForDomain(domain, `certificate.crt`));
|
79 | }
|
80 |
|
81 | export function configuredDomains() {
|
82 | return readdir(domainsDir);
|
83 | }
|
84 |
|
85 | export function removeDomain(domain: string) {
|
86 | return rimraf.sync(pathForDomain(domain));
|
87 | } |
\ | No newline at end of file |