@small-tech/auto-encrypt 3.1.0 → 4.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 CHANGED
@@ -1,12 +1,20 @@
1
1
  # Auto Encrypt
2
2
 
3
- Adds automatic provisioning and renewal of [Let’s Encrypt](https://letsencrypt.org) TLS certificates with [OCSP Stapling](https://letsencrypt.org/docs/integration-guide/#implement-ocsp-stapling) to [Node.js](https://nodejs.org) [https](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) servers (including [Express.js](https://expressjs.com/), etc.)
3
+ Automatically provisions and renews [Let’s Encrypt](https://letsencrypt.org) TLS certificates on [Node.js](https://nodejs.org) [https](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) servers (including [Kitten](https://kitten.small-web.org), [Polka](https://github.com/lukeed/polka/tree/next), [Express.js](https://expressjs.com/), etc.)
4
+
5
+ Implements the subset of RFC 8555 – Automatic Certificate Management Environment (ACME) – necessary for a client to support TLS certificate provisioning from Let’s Encrypt using HTTP-01 challenges.
4
6
 
5
7
  ## How it works
6
8
 
7
- The first time your web site is hit, it will take a couple of seconds to load as your Let’s Encrypt TLS certificates are automatically provisioned for you. From there on, your certificates will be seamlessly renewed 30 days before their expiry date.
9
+ The first time your web site is hit, it takes a couple of seconds to load as your Let’s Encrypt TLS certificates are automatically provisioned for you. From there on, your certificates are seamlessly renewed 30 days before their expiry date.
10
+
11
+ When not provisioning certificates, Auto Encrypt also forwards HTTP calls to HTTPS on your server.
12
+
13
+ ## Compatibility
8
14
 
9
- When not provisioning certificates, Auto Encrypt will also forward HTTP calls to HTTPS on your server.
15
+ All tests pass on Node.js LTS (version 22).
16
+
17
+ [Tests fail on Node.js 19 (socket hang up error).](https://codeberg.org/small-tech/auto-encrypt/issues/3)
10
18
 
11
19
  ## Installation
12
20
 
@@ -19,30 +27,29 @@ npm i @small-tech/auto-encrypt
19
27
  ### Instructions
20
28
 
21
29
  1. Import the module:
22
-
23
- ```js
24
- import AutoEncrypt from '@small-tech/auto-encrypt'
25
- ```
30
+
31
+ ```js
32
+ import AutoEncrypt from '@small-tech/auto-encrypt'
33
+ ```
26
34
 
27
35
  2. Prefix your server creation code with a reference to the Auto Encrypt class:
28
-
29
- ```js
30
- // const server = https.createServer(…) becomes
31
- const server = AutoEncrypt.https.createServer(…)
32
- ```
36
+
37
+ ```js
38
+ // const server = https.createServer(…) becomes
39
+ const server = AutoEncrypt.https.createServer(…)
40
+ ```
33
41
 
34
42
  3. When done, close your server as you would normally:
35
-
36
- ```js
37
- server.close(() => {
38
- console.log('The server is now closed.')
39
- })
40
- ```
43
+
44
+ ```js
45
+ server.close(() => {
46
+ console.log('The server is now closed.')
47
+ })
48
+ ```
41
49
 
42
50
  ### Example
43
51
 
44
- The following code creates an HTTPS server running on port 443 with [OCSP Stapling](https://letsencrypt.org/docs/integration-guide/#implement-ocsp-stapling) that automatically provisions and renews TLS certificates from [Let’s Encrypt](https://letsencrypt.org) for the domains _<hostname>_ and _www.<hostname>_.
45
-
52
+ The following code creates an HTTPS server running on port 443 that automatically provisions and renews TLS certificates from [Let’s Encrypt](https://letsencrypt.org) for the domains _<hostname>_ and _www.<hostname>_.
46
53
 
47
54
  ```js
48
55
  import AutoEncrypt from '@small-tech/auto-encrypt'
@@ -62,7 +69,7 @@ server.close(() => {
62
69
  })
63
70
  ```
64
71
 
65
- Note that on Linux, ports 80 and 443 require special privileges. Please see [A note on Linux and the security farce that is “privileged ports”](#a-note-on-linux-and-the-security-farce-that-is-priviliged-ports). If you just need a Node web server that handles all that and more for you (or to see how to implement privilege escalation seamlessly in your own servers, see [Site.js](https://sitejs.org)).
72
+ Note that on Linux, ports 80 and 443 require special privileges. Please see [A note on Linux and the security farce that is “privileged ports”](#a-note-on-linux-and-the-security-farce-that-is-priviliged-ports). If you just need a [Small Web](https://ar.al/2024/06/24/small-web-computer-science-colloquium-at-university-of-groningen/) server that handles all that and more for you (or to see how to implement privilege escalation seamlessly in your own servers, see [Kitten](https://kitten.small-web.org)).
66
73
 
67
74
  ## Configuration
68
75
 
@@ -70,6 +77,8 @@ You can customise the default configuration by adding Auto Encrypt-specific opti
70
77
 
71
78
  You can specify the domains you want the certificate to support, whether the Let’s Encrypt staging server or a local [Pebble](https://github.com/letsencrypt/pebble) server should be used instead of the default production server (useful during development and testing), and to specify a custom settings path for your Let’s Encrypt account and certificate information to be stored in.
72
79
 
80
+ (Auto Encrypt uses [Node Pebble](https://codeberg.org/small-tech/node-pebble) to enable testing with a local Pebble server from Node.js.)
81
+
73
82
  ### Example
74
83
 
75
84
  ```js
@@ -94,9 +103,9 @@ const server = AutoEncrypt.https.createServer(options, listener)
94
103
 
95
104
  Here is the full list of Auto Encrypt options (all optional) and their defaults:
96
105
 
97
- - `domains`: the hostname of the current computer and the www subdomain at that hostname.
98
- - `server`: it will use the production server (which has [rate limits](https://letsencrypt.org/docs/rate-limits/)). Valid values are `AutoEncrypt.server.(PEBBLE|STAGING|PRODUCTION)`.
99
- - `settingsPath`: _~/.small-tech.org/auto-encrypt/_
106
+ - `domains`: the hostname of the current computer and the www subdomain at that hostname.
107
+ - `server`: it will use the production server (which has [rate limits](https://letsencrypt.org/docs/rate-limits/)). Valid values are `AutoEncrypt.server.(PEBBLE|STAGING|PRODUCTION)`.
108
+ - `settingsPath`: _~/.small-tech.org/auto-encrypt/_
100
109
 
101
110
  ## Making a graceful exit
102
111
 
@@ -104,7 +113,7 @@ When you’re ready to exit your app, just call the `server.close()` method as y
104
113
 
105
114
  ## Developer documentation
106
115
 
107
- If you want to help improve Auto Encrypt or better understand how it is structured and operates, please see the [developer documentation](https://github.com/small-tech/auto-encrypt/blob/master/developer-documentation.md).
116
+ If you want to help improve Auto Encrypt or better understand how it is structured and operates, please see the [developer documentation](https://codeberg.org/small-tech/auto-encrypt/src/branch/main/developer-documentation.md).
108
117
 
109
118
  ## Examples
110
119
 
@@ -170,18 +179,17 @@ If you’re evaluating this for a “startup” or an enterprise, let us save yo
170
179
 
171
180
  ## Client details
172
181
 
173
- Auto Encrypt does one thing and one thing well: it automatically provisions a Let’s Encrypt TLS certificate for your Node.js https servers using the HTTP-01 challenge method when your server is first hit from its hostname, serves it using OCSP Stapling, and automatically renews your certificate thereafter. And, when not provisioning certificates, it forwards any HTTP requests that your machine gets to HTTPS.
182
+ Auto Encrypt does one thing and one thing well: it automatically provisions a Let’s Encrypt TLS certificate for your Node.js https servers using the HTTP-01 challenge method when your server is first hit from its hostname, and automatically renews your certificate thereafter. When not provisioning certificates, it forwards any HTTP requests that your machine gets to HTTPS.
174
183
 
175
- Auto Encrypt __does not_ and __will not__:
184
+ __Auto Encrypt _does not_ and _will not:___
176
185
 
177
- - Implement wildcard certificates. For most [small tech](https://small-tech.org/about/#small-technology) needs (personal web sites and web apps), you will likely need no more than two domains (the root domain and, due to historic and conventional reasons, the www subdomain). You will definitely not need more than the 100 domains that are supported per certificate. If you do, chances are you are looking to use Auto Encrypt in a startup or corporate setting, which is not what its for.
178
-
179
- - Implement DNS-01 or any other methods that cannot be fully automated.
186
+ - __Implement wildcard certificates.__ For most [small tech](https://small-tech.org/about/#small-technology) needs (personal web sites and web apps), you will likely need no more than two domains (the root domain and, due to historic and conventional reasons, the www subdomain). You will definitely not need more than the 100 domains that are supported per certificate. If you do, chances are you are looking to use Auto Encrypt in a startup or corporate setting, which is not what its for.
180
187
 
188
+ - __Implement DNS-01__ or any other methods that cannot be fully automated.
181
189
 
182
190
  ## Staging and production server behaviour and rate limits
183
191
 
184
- By default, Auto Encrypt will use the Let’s Encrypt production environment. This is most likely what you want as it means that your HTTPS server will Just Work™, provisioning its TLS certificate automatically the first time the server is hit via its hostname and from thereon automatically renewing the certificate a month ahead of its expiry date.
192
+ By default, Auto Encrypt uses Let’s Encrypt’s production environment. This is most likely what you want as it means your HTTPS server will Just Work™, i.e., provision its TLS certificate automatically the first time the server is hit via its hostname and from thereon automatically renew the certificate a month ahead of its expiry date.
185
193
 
186
194
  However, be aware that the production server has [rate limits](https://letsencrypt.org/docs/rate-limits/).
187
195
 
@@ -191,31 +199,30 @@ If you do use the staging environment, be aware that browsers will reject the st
191
199
 
192
200
  Needless to say, do not add the fake certificate root to the same trust store you use for your everyday browsing.
193
201
 
194
-
195
202
  ## Related projects
196
203
 
197
204
  From lower-level to higher-level:
198
205
 
199
206
  ### Auto Encrypt Localhost
200
207
 
201
- - Source: https://source.small-tech.org/site.js/lib/auto-encrypt-localhost
202
- - Package: [@small-tech/auto-encrypt-localhost](https://www.npmjs.com/package/@small-tech/auto-encrypt-localhost)
208
+ - Source: https://codeberg.org/small-tech/auto-encrypt-localhost
209
+ - Package: [@small-tech/auto-encrypt-localhost](https://www.npmjs.com/package/@small-tech/auto-encrypt-localhost)
203
210
 
204
- Automatically provisions and installs locally-trusted TLS certificates for Node.js https servers (including Express.js, etc.) using [mkcert](https://github.com/FiloSottile/mkcert/).
211
+ Automatically provisions and installs locally-trusted TLS certificates for Node.js https servers in 100% JavaScript (without any native dependencies like mkcert and certutil).
205
212
 
206
213
  ### HTTPS
207
214
 
208
- - Source: https://source.small-tech.org/site.js/lib/https
209
- - Package: [@small-tech/https](https://www.npmjs.com/package/@small-tech/https)
215
+ - Source: https://source.small-tech.org/site.js/lib/https
216
+ - Package: [@small-tech/https](https://www.npmjs.com/package/@small-tech/https)
210
217
 
211
- A drop-in [standard Node.js HTTPS module](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) replacement with both automatic development-time (localhost) certificates via Auto Encrypt Localhost and automatic production certificates via Auto Encrypt.
218
+ Drop-in replace for the [standard Node.js HTTPS module](https://nodejs.org/dist/latest-v12.x/docs/api/https.html) replacement that automatically handles TLS certificate provisioning and renewal both at localhost (via Auto Encrypt Localhost) and at hostname (via Auto Encrypt).
212
219
 
213
- ### Site.js
220
+ ### Kitten
214
221
 
215
- - Web site: https://sitejs.org
216
- - Source: https://source.small-tech.org/site.js/app
222
+ - Site: https://kitten.small-web.org
223
+ - Source: https://codeberg.org/kitten/app
217
224
 
218
- A complete [small technology](https://small-tech.org/about/#small-technology) tool for developing, testing, and deploying a secure static or dynamic personal web site or app with zero configuration.
225
+ A [💕 Small Web](https://ar.al/2020/08/07/what-is-the-small-web/) development kit.
219
226
 
220
227
  ## Tests and coverage
221
228
 
@@ -223,7 +230,7 @@ This project aims for > 80% coverage. At a recent check, coverage was at 97.42%
223
230
 
224
231
  To see the current state of code coverage, run `npm run coverage`.
225
232
 
226
- For more details, please see the [developer documentation](https://github.com/small-tech/auto-encrypt/blob/master/developer-documentation.md#tests).
233
+ For more details, please see the [developer documentation](https://codeberg.org/small-tech/auto-encrypt/src/branch/main/developer-documentation.md#tests).
227
234
 
228
235
  ## A note on Linux and the security farce that is “privileged ports”
229
236
 
package/index.js CHANGED
@@ -14,7 +14,6 @@
14
14
  import os from 'os'
15
15
  import util from 'util'
16
16
  import https from 'https'
17
- import ocsp from 'ocsp'
18
17
  import monkeyPatchTls from './lib/staging/monkeyPatchTls.js'
19
18
  import LetsEncryptServer from './lib/LetsEncryptServer.js'
20
19
  import Configuration from './lib/Configuration.js'
@@ -24,6 +23,11 @@ import Throws from './lib/util/Throws.js'
24
23
  import HttpServer from './lib/HttpServer.js'
25
24
  import log from './lib/util/log.js'
26
25
 
26
+ // This reverts IP address sort order to pre-Node 17 behaviour.
27
+ // See https://github.com/nodejs/node/issues/40537
28
+ import dns from 'node:dns'
29
+ dns.setDefaultResultOrder('ipv4first')
30
+
27
31
  // Custom errors thrown by the autoEncrypt function.
28
32
  const throws = new Throws({
29
33
  [Symbol.for('BusyProvisioningCertificateError')]:
@@ -72,9 +76,6 @@ export default class AutoEncrypt {
72
76
  */
73
77
  static get https () { return AutoEncrypt }
74
78
 
75
-
76
- static ocspCache = null
77
-
78
79
  /**
79
80
  * Automatically manages Let’s Encrypt certificate provisioning and renewal for Node.js
80
81
  * https servers using the HTTP-01 challenge on first hit of an HTTPS route via use of
@@ -169,7 +170,7 @@ export default class AutoEncrypt {
169
170
  }
170
171
  }
171
172
 
172
- const server = this.addOcspStapling(https.createServer(options, listener))
173
+ const server = https.createServer(options, listener)
173
174
 
174
175
  //
175
176
  // Monkey-patch the server.
@@ -207,25 +208,11 @@ export default class AutoEncrypt {
207
208
  }
208
209
 
209
210
 
210
- /**
211
- * The OCSP module does not have a means of clearing its cache check timers
212
- * so we do it here. (Otherwise, the test suite would hang.)
213
- */
214
- static clearOcspCacheTimers () {
215
- if (this.ocspCache !== null) {
216
- const cacheIds = Object.keys(this.ocspCache.cache)
217
- cacheIds.forEach(cacheId => {
218
- clearInterval(this.ocspCache.cache[cacheId].timer)
219
- })
220
- }
221
- }
222
-
223
211
  /**
224
212
  * Shut Auto Encrypt down. Do this before app exit. Performs necessary clean-up and removes
225
213
  * any references that might cause the app to not exit.
226
214
  */
227
215
  static shutdown () {
228
- this.clearOcspCacheTimers()
229
216
  this.certificate.stopCheckingForRenewal()
230
217
  }
231
218
 
@@ -233,64 +220,6 @@ export default class AutoEncrypt {
233
220
  // Private.
234
221
  //
235
222
 
236
- /**
237
- * Adds Online Certificate Status Protocol (OCSP) stapling (also known as TLS Certificate Status Request extension)
238
- * support to the passed server instance.
239
- *
240
- * @private
241
- * @param {https.Server} server HTTPS server instance without OCSP Stapling support.
242
- * @returns {https.Server} HTTPS server instance with OCSP Stapling support.
243
- */
244
- static addOcspStapling(server) {
245
- // OCSP stapling
246
- //
247
- // Many browsers will fetch OCSP from Let’s Encrypt when they load your site. This is a performance and privacy
248
- // problem. Ideally, connections to your site should not wait for a secondary connection to Let’s Encrypt. Also,
249
- // OCSP requests tell Let’s Encrypt which sites people are visiting. We have a good privacy policy and do not record
250
- // individually identifying details from OCSP requests, we’d rather not even receive the data in the first place.
251
- // Additionally, we anticipate our bandwidth costs for serving OCSP every time a browser visits a Let’s Encrypt site
252
- // for the first time will be a big part of our infrastructure expense.
253
- //
254
- // By turning on OCSP Stapling, you can improve the performance of your website, provide better privacy protections
255
- // … and help Let’s Encrypt efficiently serve as many people as possible.
256
- //
257
- // (Source: https://letsencrypt.org/docs/integration-guide/implement-ocsp-stapling)
258
-
259
- this.ocspCache = new ocsp.Cache()
260
- const cache = this.ocspCache
261
-
262
- server.on('OCSPRequest', (certificate, issuer, callback) => {
263
-
264
- if (certificate == null) {
265
- return callback(new Error('Cannot OCSP staple: certificate not yet provisioned.'))
266
- }
267
-
268
- ocsp.getOCSPURI(certificate, function(error, uri) {
269
- if (error) return callback(error)
270
- if (uri === null) return callback()
271
-
272
- const request = ocsp.request.generate(certificate, issuer)
273
-
274
- cache.probe(request.id, (error, cached) => {
275
- if (error) return callback(error)
276
-
277
- if (cached !== false) {
278
- return callback(null, cached.response)
279
- }
280
-
281
- const options = {
282
- url: uri,
283
- ocsp: request.data
284
- }
285
-
286
- cache.request(request.id, options, callback);
287
- })
288
- })
289
- })
290
-
291
- return server
292
- }
293
-
294
223
  // Custom object description for console output (for debugging).
295
224
  static [util.inspect.custom] () {
296
225
  return `
@@ -369,7 +369,7 @@ export default class Certificate {
369
369
  const issuer = certificate.issuer.value[0][0].value.toString('utf-8').slice(2).trim()
370
370
  const issuedAt = new Date(certificate.validity.notBefore.value)
371
371
  const expiresAt = new Date(certificate.validity.notAfter.value)
372
- const subject = certificate.subject.value[0][0].value.toString('utf-8').slice(2).trim()
372
+ const subject = certificate.subject.value.length > 0 ? certificate.subject.value[0][0].value.toString('utf-8').slice(2).trim() : '(No subject)'
373
373
 
374
374
  const alternativeNames = ((certificate.extensions.filter(extension => {
375
375
  return extension.extnID === 'subjectAlternativeName'
package/lib/HttpServer.js CHANGED
@@ -18,7 +18,7 @@
18
18
  // B. At all other times:
19
19
  // ======================
20
20
  //
21
- // Forwards http requests to https requests using a 302 redirect.
21
+ // Forwards http requests to https requests using a 307 redirect.
22
22
  //
23
23
  // Copyright © 2020 Aral Balkan, Small Technology Foundation.
24
24
  // License: AGPLv3 or later.
@@ -27,7 +27,6 @@
27
27
 
28
28
  import http from 'http'
29
29
  import encodeUrl from 'encodeurl'
30
- import enableDestroy from 'server-destroy'
31
30
  import log from './util/log.js'
32
31
 
33
32
  export default class HttpServer {
@@ -120,18 +119,13 @@ export default class HttpServer {
120
119
  response.end()
121
120
  }
122
121
  })
123
-
124
- // Enable server to be destroyed without waiting for any existing connections to close.
125
- // (While there shouldn’t be any existing connections and while the likelihood of someone
126
- // trying to denial-of-service this very low, it’s still the right thing to do.)
127
- enableDestroy(this.server)
128
122
  }
129
123
 
130
124
  set challengeServer (state) {
131
125
  if (state) {
132
126
  log(` 🔒 ❨auto-encrypt❩ HTTP server is now only responding to Let’s Encrypt challenges.`)
133
127
  } else {
134
- log(` 🔒 ❨auto-encrypt❩ HTTP server is now forwarding HTTP requests to HTTPS (302).`)
128
+ log(` 🔒 ❨auto-encrypt❩ HTTP server is now forwarding HTTP requests to HTTPS (307).`)
135
129
  }
136
130
  this.#isChallengeServer = state
137
131
  }
@@ -156,16 +150,16 @@ export default class HttpServer {
156
150
 
157
151
  async destroy () {
158
152
  // Starts killing all connections and closes the server.
159
- this.server.destroy()
153
+ this.server.closeAllConnections()
160
154
 
161
- // Wait until the server is closed before returning.
162
155
  await new Promise((resolve, reject) => {
163
- this.server.on('close', () => {
156
+ this.server.close(error => {
157
+ if (error) {
158
+ console.error(error)
159
+ reject(error)
160
+ }
164
161
  resolve()
165
162
  })
166
- this.server.on('error', (error) => {
167
- reject(error)
168
- })
169
163
  })
170
164
  }
171
165
  }
package/lib/Order.js CHANGED
@@ -31,6 +31,7 @@ const throws = new Throws()
31
31
  export default class Order {
32
32
  #data = null
33
33
  #headers = null
34
+ #location = null
34
35
  #order = null
35
36
  #certificate = null
36
37
  #certificateIdentity = null
@@ -65,6 +66,10 @@ export default class Order {
65
66
  get data () { return this.#data }
66
67
  set data (value) {
67
68
  this.#data = value
69
+ // It seems that Let’s Encrypt are no longer sending the location
70
+ // back on status checks, only on order finalisation, so let’s\
71
+ // make sure we don’t accidentally.
72
+ if (this.#data.headers.location !== undefined) this.#location = this.#data.headers.location
68
73
  this.#headers = this.#data.headers
69
74
  this.#order = this.#data.body
70
75
  }
@@ -168,10 +173,12 @@ export default class Order {
168
173
  try {
169
174
  if (numAttempts === 1) {
170
175
  // Finalise using CSR.
176
+ log(' 📝 ❨auto-encrypt❩ Finalising using CSR.')
171
177
  this.data = await (new FinaliseOrderRequest()).execute(this.finaliseUrl, csr)
172
178
  } else {
173
179
  // Check for order status.
174
- this.data = await (new CheckOrderStatusRequest()).execute(this.#headers.location)
180
+ log(' 👀 ❨auto-encrypt❩ Checking for order status.')
181
+ this.data = await (new CheckOrderStatusRequest()).execute(this.#location)
175
182
  }
176
183
  } catch (error) {
177
184
  // TODO: Handle error.
package/lib/acmeCsr.js CHANGED
@@ -53,12 +53,6 @@ function csrAsPem (domains, key) {
53
53
  extensions: [{
54
54
  name: 'subjectAltName',
55
55
  altNames
56
- }, {
57
- // OCSP Must Staple
58
- // RFC 7633. Also see https://scotthelme.co.uk/ocsp-must-staple/
59
- // 1.3.6.1.5.5.7.1.24 = DER(3003020105) (Sequence > Int > 5) *smh* ASN.1 is devil spawn.
60
- id: '1.3.6.1.5.5.7.1.24',
61
- value: forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [ forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.INTEGER, false, forge.asn1.integerToDer(5).getBytes())])
62
56
  }]
63
57
  }])
64
58
 
@@ -8,7 +8,6 @@ import fs from 'fs'
8
8
  import os from 'os'
9
9
  import path from 'path'
10
10
  import http from 'http'
11
- import enableServerDestroy from 'server-destroy'
12
11
  import Configuration from '../Configuration.js'
13
12
  import LetsEncryptServer from '../LetsEncryptServer.js'
14
13
  import Throws from '../util/Throws.js'
@@ -19,7 +18,7 @@ import log from '../util/log.js'
19
18
  //
20
19
 
21
20
  const throws = new Throws({
22
- [Symbol.for('MockServerCouldNotBeStartedError')]: details => `Mock server could not be started (${error})`
21
+ [Symbol.for('MockServerCouldNotBeStartedError')]: error => `Mock server could not be started (${error})`
23
22
  })
24
23
 
25
24
  export class MockServer {
@@ -45,7 +44,6 @@ export class MockServer {
45
44
 
46
45
  async create () {
47
46
  const server = http.createServer(this.#responseHandler)
48
- enableServerDestroy(server)
49
47
  this.#server = server
50
48
  await new Promise((resolve, reject) => {
51
49
  try {
@@ -60,12 +58,21 @@ export class MockServer {
60
58
  }
61
59
 
62
60
  async destroy () {
63
- this.#server.destroy()
61
+ this.#server.closeAllConnections()
62
+ return new Promise((resolve, reject) => {
63
+ this.#server.close(error => {
64
+ if (error) {
65
+ console.error(error)
66
+ reject(error)
67
+ }
68
+ resolve()
69
+ })
70
+ })
64
71
  }
65
72
  }
66
73
 
67
74
  export async function httpServerWithResponse (mockResponse) {
68
- return new Promise((resolve, reject) => {
75
+ return new Promise((resolve, _reject) => {
69
76
  const server = http.createServer((request, response) => {
70
77
  response.statusCode = mockResponse.statusCode
71
78
  response.end(mockResponse.body)
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@small-tech/auto-encrypt",
3
- "version": "3.1.0",
4
- "description": "Adds automatic provisioning and renewal of Let’s Encrypt TLS certificates with OCSP Stapling to Node.js https servers (including Express.js, etc.)",
3
+ "version": "4.1.0",
4
+ "description": "Automatically provisions and renews Let’s Encrypt TLS certificates on Node.js https servers (including Kitten, Polka, Express.js, etc.)",
5
+ "engines": {
6
+ "node": ">=18.2.0"
7
+ },
5
8
  "keywords": [
6
9
  "let's encrypt",
7
10
  "acme",
@@ -10,6 +13,7 @@
10
13
  "tls",
11
14
  "auto encrypt",
12
15
  "small tech",
16
+ "small web",
13
17
  "automatic"
14
18
  ],
15
19
  "author": {
@@ -60,24 +64,19 @@
60
64
  ]
61
65
  },
62
66
  "dependencies": {
63
- "bent": "aral/bent#errors-with-response-headers",
67
+ "bent": "^7.3.12",
64
68
  "encodeurl": "^1.0.2",
65
- "jose": "^1.24.0",
66
- "moment": "^2.24.0",
67
- "node-forge": "^1.3.1",
68
- "ocsp": "^1.2.0",
69
- "server-destroy": "^1.0.1"
69
+ "jose": "^1.28.2",
70
+ "moment": "^2.29.4",
71
+ "node-forge": "^1.3.1"
70
72
  },
71
73
  "devDependencies": {
72
74
  "@small-tech/esm-tape-runner": "^1.0.3",
73
- "@small-tech/node-pebble": "^4.2.4",
75
+ "@small-tech/node-pebble": "^5.1.3",
74
76
  "@small-tech/tap-monkey": "^1.3.0",
75
- "c8": "^7.11.3",
76
- "dependency-cruiser": "^9.15.1",
77
- "esbuild": "^0.8.53",
78
- "jsdoc": "^3.6.6",
77
+ "c8": "^7.12.0",
78
+ "dependency-cruiser": "^12.3.0",
79
79
  "jsdoc-to-markdown": "^6.0.1",
80
- "tape": "^5.2.1",
81
- "wtfnode": "^0.8.1"
80
+ "tape": "^5.2.1"
82
81
  }
83
82
  }