2
2
import { promisify } from "node:util" ;
3
3
import nodeOS from "node:os" ;
4
4
import { promises as fs } from "node:fs" ;
5
+ import { mkdir , writeFile } from "node:fs/promises" ;
5
6
import type nodeForge from "node-forge" ;
6
7
import forge from "node-forge" ;
7
8
import ipRegex from "ip-regex" ;
8
9
import { defu } from "defu" ;
10
+ import { resolve } from "pathe" ;
9
11
import type { Certificate , HTTPSOptions } from "./types" ;
10
12
13
+ const certificateDirectory = "node_modules/.listhen/certs/" ;
14
+
11
15
export interface CertificateOptions {
12
16
validityDays : number ;
13
17
subject : nodeForge . pki . CertificateField [ ] ;
@@ -40,10 +44,34 @@ export interface TLSCertOptions
40
44
passphrase ?: string ;
41
45
}
42
46
47
+ function pathExists ( path : string ) {
48
+ return new Promise ( ( resolve ) => {
49
+ fs . access ( path , fs . constants . F_OK )
50
+ . then ( ( ) => resolve ( true ) )
51
+ . catch ( ( ) => resolve ( false ) ) ;
52
+ } ) ;
53
+ }
54
+
43
55
export async function resolveCertificate (
44
56
options : HTTPSOptions ,
45
57
) : Promise < Certificate > {
46
58
let https : Certificate ;
59
+
60
+ if ( typeof options === "object" && options . reuse ) {
61
+ // Reuse previously autogenerated certificates if exists
62
+ const certExists = await pathExists ( certificateDirectory + "cert.pem" ) ;
63
+ const keyExists = await pathExists ( certificateDirectory + "cert-key.pem" ) ;
64
+
65
+ if ( certExists && keyExists ) {
66
+ const cert = await fs . readFile ( certificateDirectory + "cert.pem" ) ;
67
+ const key = await fs . readFile ( certificateDirectory + "cert-key.pem" ) ;
68
+ return {
69
+ cert : cert . toString ( "utf8" ) ,
70
+ key : key . toString ( "utf8" ) ,
71
+ } ;
72
+ }
73
+ }
74
+
47
75
if ( typeof options === "object" && options . key && options . cert ) {
48
76
// Resolve actual certificate and cert
49
77
https = await resolveCert ( options ) ;
@@ -95,6 +123,10 @@ async function generateCertificates(
95
123
caOptions . passphrase = options . signingKeyPassphrase ;
96
124
const ca = await generateCACert ( caOptions ) ;
97
125
126
+ await mkdir ( resolve ( certificateDirectory ) , { recursive : true } ) ;
127
+ await writeFile ( resolve ( certificateDirectory + "ca.pem" ) , ca . cert ) ;
128
+ await writeFile ( resolve ( certificateDirectory + "ca-key.pem" ) , ca . key ) ;
129
+
98
130
const domains = Array . isArray ( options . domains )
99
131
? options . domains
100
132
: [ "localhost" , "127.0.0.1" , "::1" ] ;
@@ -106,6 +138,10 @@ async function generateCertificates(
106
138
signingKey : ca . key ,
107
139
domains,
108
140
} ) ;
141
+
142
+ await writeFile ( resolve ( certificateDirectory + "cert.pem" ) , cert . cert ) ;
143
+ await writeFile ( resolve ( certificateDirectory + "cert-key.pem" ) , cert . key ) ;
144
+
109
145
return { ca, cert } ;
110
146
}
111
147
0 commit comments