@jsenv/https-local 1.0.2 → 1.0.7

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
@@ -31,7 +31,10 @@ npm install --save-dev @jsenv/https-local
31
31
  * Read more in https://github.com/jsenv/https-local#installCertificateAuthority
32
32
  */
33
33
 
34
- import { installCertificateAuthority, verifyHostsFile } from "@jsenv/https-local"
34
+ import {
35
+ installCertificateAuthority,
36
+ verifyHostsFile,
37
+ } from "@jsenv/https-local"
35
38
 
36
39
  await installCertificateAuthority({
37
40
  tryToTrust: true,
@@ -39,7 +42,7 @@ await installCertificateAuthority({
39
42
  })
40
43
  await verifyHostsFile({
41
44
  ipMappings: {
42
- "127.0.0.1": ["localhost", "local.example"],
45
+ "127.0.0.1": ["localhost"],
43
46
  },
44
47
  tryToUpdatesHostsFile: true,
45
48
  })
@@ -70,9 +73,8 @@ node ./install_certificate_authority.mjs
70
73
  import { createServer } from "node:https"
71
74
  import { requestCertificateForLocalhost } from "@jsenv/https-local"
72
75
 
73
- const { serverCertificate, serverCertificatePrivateKey } = await requestCertificateForLocalhost({
74
- serverCertificateAltNames: ["localhost", "local.example"],
75
- })
76
+ const { serverCertificate, serverCertificatePrivateKey } =
77
+ await requestCertificateForLocalhost()
76
78
 
77
79
  const server = createServer(
78
80
  {
@@ -367,9 +369,10 @@ _requestCertificateForLocalhost_ function returns a certificate and private key
367
369
  import { createServer } from "node:https"
368
370
  import { requestCertificateForLocalhost } from "@jsenv/https-local"
369
371
 
370
- const { serverCertificate, serverCertificatePrivateKey } = await requestCertificateForLocalhost({
371
- serverCertificateAltNames: ["localhost", "local.example"],
372
- })
372
+ const { serverCertificate, serverCertificatePrivateKey } =
373
+ await requestCertificateForLocalhost({
374
+ serverCertificateAltNames: ["localhost", "local.example"],
375
+ })
373
376
  ```
374
377
 
375
378
  [installCertificateAuthority](#installCertificateAuthority) must be called before this function.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/https-local",
3
- "version": "1.0.2",
3
+ "version": "1.0.7",
4
4
  "description": "A programmatic way to generate locally trusted certificates",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -13,11 +13,10 @@
13
13
  "url": "https://github.com/jsenv/https-local"
14
14
  },
15
15
  "engines": {
16
- "node": ">=14.17.0"
16
+ "node": ">=16.13.0"
17
17
  },
18
18
  "publishConfig": {
19
- "access": "public",
20
- "registry": "https://registry.npmjs.org"
19
+ "access": "public"
21
20
  },
22
21
  "type": "module",
23
22
  "exports": {
@@ -26,14 +25,17 @@
26
25
  },
27
26
  "./*": "./*"
28
27
  },
28
+ "main": "./main.js",
29
29
  "files": [
30
30
  "/src/",
31
31
  "/main.js"
32
32
  ],
33
33
  "scripts": {
34
- "eslint-check": "node ./node_modules/eslint/bin/eslint.js .",
35
- "generate-importmap": "node ./script/importmap/generate_importmap.mjs",
36
- "measure-performances": "node ./script/performance/generate_performance_report.mjs --local",
34
+ "eslint": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
35
+ "importmap": "node ./script/importmap/importmap.mjs",
36
+ "performances": "node --expose-gc ./script/performance/generate_performance_report.mjs --log",
37
+ "test": "node ./script/test/test.mjs",
38
+ "test-with-coverage": "npm run test -- --coverage",
37
39
  "start-node-server": "node ./script/certificate/start_node_server.mjs",
38
40
  "log-root-certificate-trust": "node ./script/certificate/log_root_certificate_trust.mjs",
39
41
  "trust-root-certificate": "node ./script/certificate/trust_root_certificate.mjs",
@@ -43,39 +45,31 @@
43
45
  "remove-localhost-mappings": "node ./script/hosts/remove_localhost_mappings.mjs",
44
46
  "verify-localhost-mappings": "node ./script/hosts/verify_localhost_mappings.mjs",
45
47
  "ensure-localhost-mappings": "node ./script/hosts/ensure_localhost_mappings.mjs",
46
- "test": "node ./script/test/test.mjs",
47
- "test-with-coverage": "npm run test -- --coverage",
48
- "prettier-format": "node ./script/prettier/prettier_format.mjs",
49
- "prettier-format-stage": "npm run prettier-format -- --staged",
50
- "prettier-check": "npm run prettier-format -- --dry-run",
51
- "install-playwright": "npx playwright install-deps && npx playwright install",
52
- "prepublishOnly": "node ./script/publish/remove_postinstall.mjs",
53
- "postpublish": "node ./script/publish/restore_postinstall.mjs"
48
+ "prettier": "prettier --write .",
49
+ "playwright-install": "npx playwright install-deps && npx playwright install"
54
50
  },
55
51
  "dependencies": {
56
- "@jsenv/filesystem": "2.1.1",
52
+ "@jsenv/filesystem": "2.7.1",
57
53
  "@jsenv/logger": "4.0.1",
58
54
  "command-exists": "1.2.9",
59
55
  "is-unicode-supported": "1.1.0",
60
- "node-forge": "0.10.0",
56
+ "node-forge": "1.2.1",
61
57
  "sudo-prompt": "9.2.1",
62
- "supports-color": "9.0.2",
58
+ "supports-color": "9.2.1",
63
59
  "which": "2.0.2"
64
60
  },
65
61
  "devDependencies": {
66
- "@jsenv/assert": "2.3.0",
67
- "@jsenv/codecov-upload": "3.5.0",
68
- "@jsenv/core": "19.6.2",
69
- "@jsenv/eslint-config": "15.0.2",
70
- "@jsenv/github-release-package": "1.2.3",
71
- "@jsenv/importmap-eslint-resolver": "5.1.0",
72
- "@jsenv/importmap-node-module": "1.0.1",
73
- "@jsenv/package-publish": "1.6.2",
74
- "@jsenv/performance-impact": "1.7.0",
75
- "@jsenv/prettier-check-project": "5.6.1",
76
- "eslint": "7.32.0",
77
- "eslint-plugin-import": "2.24.0",
78
- "playwright": "1.14.0",
79
- "prettier": "2.3.2"
62
+ "@jsenv/assert": "2.4.1",
63
+ "@jsenv/core": "25.3.0",
64
+ "@jsenv/eslint-config": "16.0.9",
65
+ "@jsenv/github-release-package": "1.3.3",
66
+ "@jsenv/importmap-eslint-resolver": "5.2.5",
67
+ "@jsenv/importmap-node-module": "5.1.3",
68
+ "@jsenv/package-publish": "1.7.2",
69
+ "@jsenv/performance-impact": "2.2.4",
70
+ "eslint": "8.7.0",
71
+ "eslint-plugin-import": "2.25.4",
72
+ "playwright": "1.18.0",
73
+ "prettier": "2.5.1"
80
74
  }
81
- }
75
+ }
@@ -1,12 +1,13 @@
1
- /* eslint-disable import/max-dependencies */
2
-
3
- import { createLogger, createDetailedMessage } from "@jsenv/logger"
4
1
  import { readFile, writeFile, removeFileSystemNode } from "@jsenv/filesystem"
2
+ import { createLogger, createDetailedMessage } from "@jsenv/logger"
5
3
 
6
4
  import { infoSign, okSign } from "./internal/logs.js"
7
5
  import { getAuthorityFileInfos } from "./internal/authority_file_infos.js"
8
6
  import { attributeDescriptionFromAttributeArray } from "./internal/certificate_data_converter.js"
9
- import { formatTimeDelta, formatDuration } from "./internal/validity_formatting.js"
7
+ import {
8
+ formatTimeDelta,
9
+ formatDuration,
10
+ } from "./internal/validity_formatting.js"
10
11
  import { importNodeForge } from "./internal/forge.js"
11
12
  import { createAuthorityRootCertificate } from "./internal/certificate_generator.js"
12
13
  import { importPlatformMethods } from "./internal/platform.js"
@@ -54,8 +55,11 @@ export const installCertificateAuthority = async ({
54
55
  )
55
56
  }
56
57
 
57
- const { authorityJsonFileInfo, rootCertificateFileInfo, rootCertificatePrivateKeyFileInfo } =
58
- getAuthorityFileInfos()
58
+ const {
59
+ authorityJsonFileInfo,
60
+ rootCertificateFileInfo,
61
+ rootCertificatePrivateKeyFileInfo,
62
+ } = getAuthorityFileInfos()
59
63
  const authorityJsonFileUrl = authorityJsonFileInfo.url
60
64
  const rootCertificateFileUrl = rootCertificateFileInfo.url
61
65
  const rootPrivateKeyFileUrl = rootCertificatePrivateKeyFileInfo.url
@@ -76,16 +80,23 @@ export const installCertificateAuthority = async ({
76
80
  })
77
81
 
78
82
  const { pki } = await importNodeForge()
79
- const rootCertificate = pemAsFileContent(pki.certificateToPem(rootCertificateForgeObject))
83
+ const rootCertificate = pemAsFileContent(
84
+ pki.certificateToPem(rootCertificateForgeObject),
85
+ )
80
86
  const rootCertificatePrivateKey = pemAsFileContent(
81
87
  pki.privateKeyToPem(rootCertificatePrivateKeyForgeObject),
82
88
  )
83
89
 
84
90
  await writeFile(rootCertificateFileUrl, rootCertificate)
85
91
  await writeFile(rootPrivateKeyFileUrl, rootCertificatePrivateKey)
86
- await writeFile(authorityJsonFileUrl, JSON.stringify({ serialNumber: 0 }, null, " "))
92
+ await writeFile(
93
+ authorityJsonFileUrl,
94
+ JSON.stringify({ serialNumber: 0 }, null, " "),
95
+ )
87
96
 
88
- logger.info(`${okSign} authority root certificate written at ${rootCertificateFileInfo.path}`)
97
+ logger.info(
98
+ `${okSign} authority root certificate written at ${rootCertificateFileInfo.path}`,
99
+ )
89
100
  return {
90
101
  rootCertificateForgeObject,
91
102
  rootCertificatePrivateKeyForgeObject,
@@ -140,14 +151,18 @@ export const installCertificateAuthority = async ({
140
151
  logger.debug(
141
152
  `Authority root certificate is not on filesystem at ${rootCertificateFileInfo.path}`,
142
153
  )
143
- logger.info(`${infoSign} authority root certificate not found in filesystem`)
154
+ logger.info(
155
+ `${infoSign} authority root certificate not found in filesystem`,
156
+ )
144
157
  return generate()
145
158
  }
146
159
  if (!rootCertificatePrivateKeyFileInfo.exists) {
147
160
  logger.debug(
148
161
  `Authority root certificate private key is not on filesystem at ${rootCertificatePrivateKeyFileInfo.path}`,
149
162
  )
150
- logger.info(`${infoSign} authority root certificate not found in filesystem`)
163
+ logger.info(
164
+ `${infoSign} authority root certificate not found in filesystem`,
165
+ )
151
166
  return generate()
152
167
  }
153
168
  logger.debug(
@@ -155,18 +170,23 @@ export const installCertificateAuthority = async ({
155
170
  )
156
171
  logger.info(`${okSign} authority root certificate found in filesystem`)
157
172
 
158
- const rootCertificate = await readFile(rootCertificateFileInfo.path, { as: "string" })
173
+ const rootCertificate = await readFile(rootCertificateFileInfo.path, {
174
+ as: "string",
175
+ })
159
176
  const { pki } = await importNodeForge()
160
177
  const rootCertificateForgeObject = pki.certificateFromPem(rootCertificate)
161
178
 
162
179
  logger.info(`Checking certificate validity...`)
163
- const rootCertificateValidityDurationInMs = getCertificateValidityDurationInMs(
180
+ const rootCertificateValidityDurationInMs =
181
+ getCertificateValidityDurationInMs(rootCertificateForgeObject)
182
+ const rootCertificateValidityRemainingMs = getCertificateRemainingMs(
164
183
  rootCertificateForgeObject,
165
184
  )
166
- const rootCertificateValidityRemainingMs = getCertificateRemainingMs(rootCertificateForgeObject)
167
185
  if (rootCertificateValidityRemainingMs < 0) {
168
186
  logger.info(
169
- `${infoSign} certificate expired ${formatTimeDelta(rootCertificateValidityRemainingMs)}`,
187
+ `${infoSign} certificate expired ${formatTimeDelta(
188
+ rootCertificateValidityRemainingMs,
189
+ )}`,
170
190
  )
171
191
  return regenerate()
172
192
  }
@@ -174,30 +194,44 @@ export const installCertificateAuthority = async ({
174
194
  rootCertificateValidityRemainingMs / rootCertificateValidityDurationInMs
175
195
  if (rootCertificateValidityRemainingRatio < aboutToExpireRatio) {
176
196
  logger.info(
177
- `${infoSign} certificate will expire ${formatTimeDelta(rootCertificateValidityRemainingMs)}`,
197
+ `${infoSign} certificate will expire ${formatTimeDelta(
198
+ rootCertificateValidityRemainingMs,
199
+ )}`,
178
200
  )
179
201
  return regenerate()
180
202
  }
181
203
  logger.info(
182
- `${okSign} certificate still valid for ${formatDuration(rootCertificateValidityRemainingMs)}`,
204
+ `${okSign} certificate still valid for ${formatDuration(
205
+ rootCertificateValidityRemainingMs,
206
+ )}`,
183
207
  )
184
208
 
185
209
  logger.info(`Detect if certificate attributes have changed...`)
186
- const rootCertificateDifferences = compareRootCertificateAttributes(rootCertificateForgeObject, {
187
- certificateCommonName,
188
- certificateValidityDurationInMs,
189
- })
210
+ const rootCertificateDifferences = compareRootCertificateAttributes(
211
+ rootCertificateForgeObject,
212
+ {
213
+ certificateCommonName,
214
+ certificateValidityDurationInMs,
215
+ },
216
+ )
190
217
  if (rootCertificateDifferences.length) {
191
218
  const paramNames = Object.keys(rootCertificateDifferences)
192
- logger.info(`${infoSign} certificate attributes are outdated: ${paramNames}`)
219
+ logger.info(
220
+ `${infoSign} certificate attributes are outdated: ${paramNames}`,
221
+ )
193
222
  return regenerate()
194
223
  }
195
224
  logger.info(`${okSign} certificate attributes are the same`)
196
225
 
197
- const rootCertificatePrivateKey = await readFile(rootCertificatePrivateKeyFileInfo.path, {
198
- as: "string",
199
- })
200
- const rootCertificatePrivateKeyForgeObject = pki.privateKeyFromPem(rootCertificatePrivateKey)
226
+ const rootCertificatePrivateKey = await readFile(
227
+ rootCertificatePrivateKeyFileInfo.path,
228
+ {
229
+ as: "string",
230
+ },
231
+ )
232
+ const rootCertificatePrivateKeyForgeObject = pki.privateKeyFromPem(
233
+ rootCertificatePrivateKey,
234
+ )
201
235
 
202
236
  const trustInfo = await platformMethods.executeTrustQuery({
203
237
  logger,
@@ -272,8 +306,11 @@ export const uninstallCertificateAuthority = async ({
272
306
  logger = createLogger({ logLevel }),
273
307
  tryToUntrust = false,
274
308
  } = {}) => {
275
- const { authorityJsonFileInfo, rootCertificateFileInfo, rootCertificatePrivateKeyFileInfo } =
276
- getAuthorityFileInfos()
309
+ const {
310
+ authorityJsonFileInfo,
311
+ rootCertificateFileInfo,
312
+ rootCertificatePrivateKeyFileInfo,
313
+ } = getAuthorityFileInfos()
277
314
 
278
315
  const filesToRemove = []
279
316
 
@@ -283,7 +320,9 @@ export const uninstallCertificateAuthority = async ({
283
320
  if (rootCertificateFileInfo.exists) {
284
321
  // first untrust the root cert file
285
322
  if (tryToUntrust) {
286
- const rootCertificate = await readFile(rootCertificateFileInfo.url, { as: "string" })
323
+ const rootCertificate = await readFile(rootCertificateFileInfo.url, {
324
+ as: "string",
325
+ })
287
326
  const { pki } = await importNodeForge()
288
327
  const rootCertificateForgeObject = pki.certificateFromPem(rootCertificate)
289
328
  const rootCertificateCommonName = attributeDescriptionFromAttributeArray(
@@ -41,8 +41,11 @@ export const requestCertificateForLocalhost = async ({
41
41
  )
42
42
  }
43
43
 
44
- const { authorityJsonFileInfo, rootCertificateFileInfo, rootCertificatePrivateKeyFileInfo } =
45
- getAuthorityFileInfos()
44
+ const {
45
+ authorityJsonFileInfo,
46
+ rootCertificateFileInfo,
47
+ rootCertificatePrivateKeyFileInfo,
48
+ } = getAuthorityFileInfos()
46
49
  if (!rootCertificateFileInfo.exists) {
47
50
  throw new Error(
48
51
  `Certificate authority not found, "installCertificateAuthority" must be called before "requestCertificateForLocalhost"`,
@@ -57,16 +60,26 @@ export const requestCertificateForLocalhost = async ({
57
60
 
58
61
  logger.debug(`Restoring certificate authority from filesystem...`)
59
62
  const { pki } = await importNodeForge()
60
- const rootCertificate = await readFile(rootCertificateFileInfo.url, { as: "string" })
61
- const rootCertificatePrivateKey = await readFile(rootCertificatePrivateKeyFileInfo.url, {
63
+ const rootCertificate = await readFile(rootCertificateFileInfo.url, {
62
64
  as: "string",
63
65
  })
64
- const certificateAuthorityData = await readFile(authorityJsonFileInfo.url, { as: "json" })
66
+ const rootCertificatePrivateKey = await readFile(
67
+ rootCertificatePrivateKeyFileInfo.url,
68
+ {
69
+ as: "string",
70
+ },
71
+ )
72
+ const certificateAuthorityData = await readFile(authorityJsonFileInfo.url, {
73
+ as: "json",
74
+ })
65
75
  const rootCertificateForgeObject = pki.certificateFromPem(rootCertificate)
66
- const rootCertificatePrivateKeyForgeObject = pki.privateKeyFromPem(rootCertificatePrivateKey)
76
+ const rootCertificatePrivateKeyForgeObject = pki.privateKeyFromPem(
77
+ rootCertificatePrivateKey,
78
+ )
67
79
  logger.debug(`${okSign} certificate authority restored from filesystem`)
68
80
 
69
- const serverCertificateSerialNumber = certificateAuthorityData.serialNumber + 1
81
+ const serverCertificateSerialNumber =
82
+ certificateAuthorityData.serialNumber + 1
70
83
  await writeFile(
71
84
  authorityJsonFileInfo.url,
72
85
  JSON.stringify({ serialNumber: serverCertificateSerialNumber }, null, " "),
@@ -81,14 +94,17 @@ export const requestCertificateForLocalhost = async ({
81
94
  await requestCertificateFromAuthority({
82
95
  logger,
83
96
  authorityCertificateForgeObject: rootCertificateForgeObject,
84
- auhtorityCertificatePrivateKeyForgeObject: rootCertificatePrivateKeyForgeObject,
97
+ auhtorityCertificatePrivateKeyForgeObject:
98
+ rootCertificatePrivateKeyForgeObject,
85
99
  serialNumber: serverCertificateSerialNumber,
86
100
  altNames: serverCertificateAltNames,
87
101
  commonName: serverCertificateCommonName,
88
102
  validityDurationInMs: serverCertificateValidityDurationInMs,
89
103
  })
90
104
  const serverCertificate = pki.certificateToPem(certificateForgeObject)
91
- const serverCertificatePrivateKey = pki.privateKeyToPem(certificatePrivateKeyForgeObject)
105
+ const serverCertificatePrivateKey = pki.privateKeyToPem(
106
+ certificatePrivateKeyForgeObject,
107
+ )
92
108
  logger.debug(
93
109
  `${okSign} server certificate generated, it will be valid for ${formatDuration(
94
110
  serverCertificateValidityDurationInMs,
@@ -24,7 +24,9 @@ export const verifyHostsFile = async ({
24
24
  Object.keys(ipMappings).forEach((ip) => {
25
25
  const ipHostnames = ipMappings[ip]
26
26
  if (!Array.isArray(ipHostnames)) {
27
- throw new TypeError(`ipMappings values must be an array, found ${ipHostnames} for ${ip}`)
27
+ throw new TypeError(
28
+ `ipMappings values must be an array, found ${ipHostnames} for ${ip}`,
29
+ )
28
30
  }
29
31
  const existingMappings = hostnames.getIpHostnames(ip)
30
32
  const missingHostnames = normalizeHostnames(ipHostnames).filter(
@@ -47,15 +49,20 @@ export const verifyHostsFile = async ({
47
49
  .map(({ ip, missingHostnames }) => `${ip} ${missingHostnames.join(" ")}`)
48
50
  .join(EOL)
49
51
  logger.warn(
50
- createDetailedMessage(`${warningSign} ${formatXMappingMissingMessage(missingMappingCount)}`, {
51
- "hosts file path": hostsFilePath,
52
- "line(s) to add": linesToAdd,
53
- }),
52
+ createDetailedMessage(
53
+ `${warningSign} ${formatXMappingMissingMessage(missingMappingCount)}`,
54
+ {
55
+ "hosts file path": hostsFilePath,
56
+ "line(s) to add": linesToAdd,
57
+ },
58
+ ),
54
59
  )
55
60
  return
56
61
  }
57
62
 
58
- logger.info(`${infoSign} ${formatXMappingMissingMessage(missingMappingCount)}`)
63
+ logger.info(
64
+ `${infoSign} ${formatXMappingMissingMessage(missingMappingCount)}`,
65
+ )
59
66
  await missingMappings.reduce(async (previous, { ip, missingHostnames }) => {
60
67
  await previous
61
68
  const mapping = `${ip} ${missingHostnames.join(" ")}`
@@ -11,14 +11,20 @@ export const getAuthorityFileInfos = () => {
11
11
  rootCertificatePrivateKeyFileUrl,
12
12
  } = getCertificateAuthorityFileUrls()
13
13
 
14
- const authorityJsonFilePath = urlToFileSystemPath(certificateAuthorityJsonFileUrl)
14
+ const authorityJsonFilePath = urlToFileSystemPath(
15
+ certificateAuthorityJsonFileUrl,
16
+ )
15
17
  const authorityJsonFileDetected = existsSync(authorityJsonFilePath)
16
18
 
17
19
  const rootCertificateFilePath = urlToFileSystemPath(rootCertificateFileUrl)
18
20
  const rootCertificateFileDetected = existsSync(rootCertificateFilePath)
19
21
 
20
- const rootCertificatePrivateKeyFilePath = urlToFileSystemPath(rootCertificatePrivateKeyFileUrl)
21
- const rootCertificatePrivateKeyFileDetected = existsSync(rootCertificatePrivateKeyFilePath)
22
+ const rootCertificatePrivateKeyFilePath = urlToFileSystemPath(
23
+ rootCertificatePrivateKeyFileUrl,
24
+ )
25
+ const rootCertificatePrivateKeyFileDetected = existsSync(
26
+ rootCertificatePrivateKeyFilePath,
27
+ )
22
28
 
23
29
  return {
24
30
  authorityJsonFileInfo: {
@@ -1,4 +1,8 @@
1
- import { assertAndNormalizeDirectoryUrl, resolveUrl, urlToFilename } from "@jsenv/filesystem"
1
+ import {
2
+ assertAndNormalizeDirectoryUrl,
3
+ resolveUrl,
4
+ urlToFilename,
5
+ } from "@jsenv/filesystem"
2
6
 
3
7
  export const getCertificateAuthorityFileUrls = () => {
4
8
  // we need a directory common to every instance of @jsenv/https-local
@@ -36,9 +40,15 @@ export const getRootCertificateSymlinkUrls = ({
36
40
  const serverCertificateDirectory = resolveUrl("./", serverCertificateFileUrl)
37
41
 
38
42
  const rootCertificateFilename = urlToFilename(rootCertificateFileUrl)
39
- const rootCertificateSymlinkUrl = resolveUrl(rootCertificateFilename, serverCertificateDirectory)
43
+ const rootCertificateSymlinkUrl = resolveUrl(
44
+ rootCertificateFilename,
45
+ serverCertificateDirectory,
46
+ )
40
47
  const rootPrivateKeyFilename = urlToFilename(rootPrivateKeyFileUrl)
41
- const rootPrivateKeySymlinkUrl = resolveUrl(rootPrivateKeyFilename, serverCertificateDirectory)
48
+ const rootPrivateKeySymlinkUrl = resolveUrl(
49
+ rootPrivateKeyFilename,
50
+ serverCertificateDirectory,
51
+ )
42
52
 
43
53
  return {
44
54
  rootCertificateSymlinkUrl,
@@ -64,12 +74,18 @@ const getJsenvApplicationDirectoryUrl = () => {
64
74
  assertAndNormalizeDirectoryUrl(process.env.XDG_CONFIG_HOME),
65
75
  )
66
76
  }
67
- return resolveUrl(`./.config/https_local/`, assertAndNormalizeDirectoryUrl(process.env.HOME))
77
+ return resolveUrl(
78
+ `./.config/https_local/`,
79
+ assertAndNormalizeDirectoryUrl(process.env.HOME),
80
+ )
68
81
  }
69
82
 
70
83
  if (platform === "win32") {
71
84
  if (process.env.LOCALAPPDATA) {
72
- return resolveUrl(`./https_local/`, assertAndNormalizeDirectoryUrl(process.env.LOCALAPPDATA))
85
+ return resolveUrl(
86
+ `./https_local/`,
87
+ assertAndNormalizeDirectoryUrl(process.env.LOCALAPPDATA),
88
+ )
73
89
  }
74
90
 
75
91
  return resolveUrl(
@@ -34,7 +34,9 @@ const isUrl = (value) => {
34
34
  }
35
35
  }
36
36
 
37
- export const extensionArrayFromExtensionDescription = (extensionDescription) => {
37
+ export const extensionArrayFromExtensionDescription = (
38
+ extensionDescription,
39
+ ) => {
38
40
  const extensionArray = []
39
41
  Object.keys(extensionDescription).forEach((key) => {
40
42
  const value = extensionDescription[key]
@@ -65,7 +67,9 @@ export const attributeDescriptionFromAttributeArray = (attributeArray) => {
65
67
  return attributeObject
66
68
  }
67
69
 
68
- export const attributeArrayFromAttributeDescription = (attributeDescription) => {
70
+ export const attributeArrayFromAttributeDescription = (
71
+ attributeDescription,
72
+ ) => {
69
73
  const attributeArray = []
70
74
  Object.keys(attributeDescription).forEach((key) => {
71
75
  const value = attributeDescription[key]
@@ -33,7 +33,9 @@ export const createAuthorityRootCertificate = async ({
33
33
  rootCertificateForgeObject.publicKey = rootCertificatePublicKeyForgeObject
34
34
  rootCertificateForgeObject.serialNumber = serialNumber.toString(16)
35
35
  rootCertificateForgeObject.validity.notBefore = new Date()
36
- rootCertificateForgeObject.validity.notAfter = new Date(Date.now() + validityDurationInMs)
36
+ rootCertificateForgeObject.validity.notAfter = new Date(
37
+ Date.now() + validityDurationInMs,
38
+ )
37
39
  rootCertificateForgeObject.setSubject(
38
40
  attributeArrayFromAttributeDescription({
39
41
  commonName,
@@ -109,7 +111,9 @@ export const requestCertificateFromAuthority = async ({
109
111
  )
110
112
  }
111
113
  if (typeof serialNumber !== "number") {
112
- throw new TypeError(`serialNumber must be a number but received ${serialNumber}`)
114
+ throw new TypeError(
115
+ `serialNumber must be a number but received ${serialNumber}`,
116
+ )
113
117
  }
114
118
 
115
119
  const forge = await importNodeForge()
@@ -122,16 +126,23 @@ export const requestCertificateFromAuthority = async ({
122
126
  certificateForgeObject.publicKey = certificatePublicKeyForgeObject
123
127
  certificateForgeObject.serialNumber = serialNumber.toString(16)
124
128
  certificateForgeObject.validity.notBefore = new Date()
125
- certificateForgeObject.validity.notAfter = new Date(Date.now() + validityDurationInMs)
129
+ certificateForgeObject.validity.notAfter = new Date(
130
+ Date.now() + validityDurationInMs,
131
+ )
126
132
 
127
133
  const attributeDescription = {
128
- ...attributeDescriptionFromAttributeArray(authorityCertificateForgeObject.subject.attributes),
134
+ ...attributeDescriptionFromAttributeArray(
135
+ authorityCertificateForgeObject.subject.attributes,
136
+ ),
129
137
  commonName,
130
138
  // organizationName: serverCertificateOrganizationName
131
139
  }
132
- const attributeArray = attributeArrayFromAttributeDescription(attributeDescription)
140
+ const attributeArray =
141
+ attributeArrayFromAttributeDescription(attributeDescription)
133
142
  certificateForgeObject.setSubject(attributeArray)
134
- certificateForgeObject.setIssuer(authorityCertificateForgeObject.subject.attributes)
143
+ certificateForgeObject.setIssuer(
144
+ authorityCertificateForgeObject.subject.attributes,
145
+ )
135
146
  certificateForgeObject.setExtensions(
136
147
  extensionArrayFromExtensionDescription({
137
148
  basicConstraints: {
@@ -159,7 +170,10 @@ export const requestCertificateFromAuthority = async ({
159
170
  },
160
171
  }),
161
172
  )
162
- certificateForgeObject.sign(auhtorityCertificatePrivateKeyForgeObject, forge.sha256.create())
173
+ certificateForgeObject.sign(
174
+ auhtorityCertificatePrivateKeyForgeObject,
175
+ forge.sha256.create(),
176
+ )
163
177
 
164
178
  return {
165
179
  certificateForgeObject,
@@ -4,5 +4,6 @@ const require = createRequire(import.meta.url)
4
4
 
5
5
  export const commandExists = async (command) => {
6
6
  const { sync } = require("command-exists")
7
- return sync(command)
7
+ const exists = sync(command)
8
+ return exists
8
9
  }
@@ -1,6 +1,9 @@
1
1
  import { exec as nodeExec } from "node:child_process"
2
2
 
3
- export const exec = (command, { cwd, input, onLog = () => {}, onErrorLog = () => {} } = {}) => {
3
+ export const exec = (
4
+ command,
5
+ { cwd, input, onLog = () => {}, onErrorLog = () => {} } = {},
6
+ ) => {
4
7
  return new Promise((resolve, reject) => {
5
8
  const commandProcess = nodeExec(
6
9
  command,