@jsenv/https-local 3.0.0 → 3.0.2

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
@@ -18,7 +18,8 @@ npm install --save-dev @jsenv/https-local
18
18
 
19
19
  ```js
20
20
  /*
21
- * This file needs to be executed once. After that the root certificate is valid for 20 years.
21
+ * This file needs to be executed once.
22
+ * After that the root certificate is valid for 20 years.
22
23
  * Re-executing this file will log the current root certificate validity and trust status.
23
24
  * Re-executing this file 20 years later would reinstall a root certificate and re-trust it.
24
25
  *
@@ -42,7 +43,7 @@ await verifyHostsFile({
42
43
  })
43
44
  ```
44
45
 
45
- 3 - Run file to install certificate authority with node
46
+ 3 - Run with node
46
47
 
47
48
  ```console
48
49
  node ./install_certificate_authority.mjs
@@ -88,14 +89,14 @@ server.listen(8080)
88
89
  console.log(`Server listening at https://local.example:8080`)
89
90
  ```
90
91
 
91
- 5 - Run file to start server with node
92
+ 5 - Start server with node
92
93
 
93
94
  ```console
94
95
  node ./start_dev_server.mjs
95
96
  ```
96
97
 
97
- At this stage of the documentation you have a server running in https.
98
- The rest of the documentation goes into details.
98
+ At this stage you have a server running in https.
99
+ The rest of this documentation goes into more details.
99
100
 
100
101
  # Certificate expiration
101
102
 
@@ -104,9 +105,11 @@ The rest of the documentation goes into details.
104
105
  | server | 1 year | Re-run _requestCertificate_ |
105
106
  | authority | 20 year | Re-run _installCertificateAuthority_ |
106
107
 
107
- The **server** certificate expires after one year which is the maximum duration allowed by web browsers. In the unlikely scenario where your local server is running for more than a year without interruption, restart it and you're good for one more year.
108
+ The **server certificate** expires after one year which is the maximum duration allowed by web browsers.
109
+ In the unlikely scenario where a local server is running for more than a year without interruption, restart it to re-run requestCertificate.
108
110
 
109
- The **authority** root certificate expires after 20 years which is close to the maximum allowed duration. In the very unlikely scenario where you are using the same machine for more than 20 years, re-execute [installCertificateAuthority](#installCertificateAuthority) to update certificate authority then restart your server.
111
+ The **authority root certificate** expires after 20 years which is close to the maximum allowed duration.
112
+ In the very unlikely scenario where you are using the same machine for more than 20 years, re-execute [installCertificateAuthority](#installCertificateAuthority) to update certificate authority then restart your server.
110
113
 
111
114
  # installCertificateAuthority
112
115
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/https-local",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "A programmatic way to generate locally trusted certificates",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -44,28 +44,28 @@
44
44
  "verify-localhost-mappings": "node ./scripts/hosts/verify_localhost_mappings.mjs",
45
45
  "ensure-localhost-mappings": "node ./scripts/hosts/ensure_localhost_mappings.mjs",
46
46
  "prettier": "prettier --write .",
47
- "playwright-install": "npx playwright install-deps && npx playwright install"
47
+ "playwright:install": "npx playwright install-deps && npx playwright install"
48
48
  },
49
49
  "dependencies": {
50
- "@jsenv/filesystem": "4.1.2",
51
- "@jsenv/log": "3.1.0",
52
- "@jsenv/urls": "1.2.7",
50
+ "@jsenv/filesystem": "4.1.6",
51
+ "@jsenv/log": "3.3.2",
52
+ "@jsenv/urls": "1.2.8",
53
53
  "command-exists": "1.2.9",
54
54
  "node-forge": "1.3.1",
55
55
  "sudo-prompt": "9.2.1",
56
- "which": "2.0.2"
56
+ "which": "3.0.0"
57
57
  },
58
58
  "devDependencies": {
59
- "@jsenv/assert": "2.6.0",
60
- "@jsenv/core": "28.0.2",
61
- "@jsenv/eslint-config": "16.2.1",
62
- "@jsenv/eslint-import-resolver": "0.3.0",
63
- "@jsenv/github-release-package": "1.5.0",
64
- "@jsenv/package-publish": "1.10.0",
65
- "@jsenv/performance-impact": "2.3.0",
66
- "eslint": "8.21.0",
59
+ "@jsenv/assert": "2.8.0",
60
+ "@jsenv/core": "30.0.0",
61
+ "@jsenv/eslint-config": "16.2.9",
62
+ "@jsenv/eslint-import-resolver": "0.4.1",
63
+ "@jsenv/github-release-package": "1.5.1",
64
+ "@jsenv/package-publish": "1.10.1",
65
+ "@jsenv/performance-impact": "4.1.0",
66
+ "eslint": "8.30.0",
67
67
  "eslint-plugin-import": "2.26.0",
68
- "playwright": "1.24.2",
69
- "prettier": "2.7.1"
68
+ "playwright": "1.29.1",
69
+ "prettier": "2.8.1"
70
70
  }
71
71
  }
@@ -0,0 +1,7 @@
1
+ import { existsSync } from "node:fs"
2
+
3
+ export const detectBrowser = (pathCandidates) => {
4
+ return pathCandidates.some((pathCandidate) => {
5
+ return existsSync(pathCandidate)
6
+ })
7
+ }
@@ -1,4 +1,3 @@
1
- import { existsSync } from "node:fs"
2
1
  import { execSync } from "node:child_process"
3
2
  import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
4
3
  import { UNICODE } from "@jsenv/log"
@@ -35,22 +34,15 @@ export const executeTrustQueryOnChrome = ({
35
34
  getCertutilBinPath,
36
35
 
37
36
  browserName: "chrome",
38
- detectBrowser: () => {
39
- logger.debug(`Detecting Chrome...`)
40
- const chromeBinFileExists = existsSync("/usr/bin/google-chrome")
41
-
42
- if (chromeBinFileExists) {
43
- logger.debug(`${UNICODE.OK} Chrome detected`)
44
- return true
45
- }
46
-
47
- logger.debug(`${UNICODE.INFO} Chrome not detected`)
48
- return false
49
- },
50
- browserNSSDBDirectoryUrl: new URL(
51
- ".pki/nssdb",
52
- assertAndNormalizeDirectoryUrl(process.env.HOME),
53
- ).href,
37
+ browserPaths: ["/usr/bin/google-chrome"],
38
+ browserNSSDBDirectoryUrls: [
39
+ new URL(".pki/nssdb", assertAndNormalizeDirectoryUrl(process.env.HOME)),
40
+ new URL(
41
+ "snap/chromium/current/.pki/nssdb",
42
+ assertAndNormalizeDirectoryUrl(process.env.HOME),
43
+ ), // Snapcraft
44
+ "file:///etc/pki/nssdb", // CentOS 7
45
+ ],
54
46
  getBrowserClosedPromise: async () => {
55
47
  if (!isChromeOpen()) {
56
48
  return
@@ -1,4 +1,3 @@
1
- import { existsSync } from "node:fs"
2
1
  import { execSync } from "node:child_process"
3
2
  import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
4
3
  import { UNICODE } from "@jsenv/log"
@@ -35,22 +34,22 @@ export const executeTrustQueryOnFirefox = ({
35
34
  getCertutilBinPath,
36
35
 
37
36
  browserName: "firefox",
38
- detectBrowser: () => {
39
- logger.debug(`Detecting Firefox...`)
40
- const firefoxBinFileExists = existsSync("/usr/bin/firefox")
41
-
42
- if (firefoxBinFileExists) {
43
- logger.debug(`${UNICODE.OK} Firefox detected`)
44
- return true
45
- }
46
-
47
- logger.debug(`${UNICODE.INFO} Firefox not detected`)
48
- return false
49
- },
50
- browserNSSDBDirectoryUrl: new URL(
51
- ".mozilla/firefox/",
52
- assertAndNormalizeDirectoryUrl(process.env.HOME),
53
- ).href,
37
+ browserPaths: [
38
+ "/usr/bin/firefox",
39
+ "/usr/bin/firefox-nightly",
40
+ "/usr/bin/firefox-developer-edition",
41
+ "/snap/firefox",
42
+ ],
43
+ browserNSSDBDirectoryUrls: [
44
+ new URL(
45
+ ".mozilla/firefox/",
46
+ assertAndNormalizeDirectoryUrl(process.env.HOME),
47
+ ),
48
+ new URL(
49
+ "/snap/firefox/common/.mozilla/firefox/",
50
+ assertAndNormalizeDirectoryUrl(process.env.HOME),
51
+ ),
52
+ ],
54
53
  getBrowserClosedPromise: async () => {
55
54
  if (!isFirefoxOpen()) {
56
55
  return
@@ -1,4 +1,3 @@
1
- import { existsSync } from "node:fs"
2
1
  import { execSync } from "node:child_process"
3
2
  import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
4
3
  import { UNICODE, createTaskLog } from "@jsenv/log"
@@ -35,22 +34,18 @@ export const executeTrustQueryOnFirefox = ({
35
34
  getCertutilBinPath,
36
35
 
37
36
  browserName: "firefox",
38
- detectBrowser: () => {
39
- logger.debug(`Detecting firefox...`)
40
- const firefoxDetected = existsSync("/Applications/Firefox.app")
41
-
42
- if (firefoxDetected) {
43
- logger.debug(`${UNICODE.OK} firefox detected`)
44
- return true
45
- }
46
-
47
- logger.debug(`${UNICODE.INFO} firefox not detected`)
48
- return false
49
- },
50
- browserNSSDBDirectoryUrl: new URL(
51
- `./Library/Application Support/Firefox/Profiles/`,
52
- assertAndNormalizeDirectoryUrl(process.env.HOME),
53
- ).href,
37
+ browserPaths: [
38
+ "/Applications/Firefox.app",
39
+ "/Applications/FirefoxDeveloperEdition.app",
40
+ "/Applications/Firefox Developer Edition.app",
41
+ "/Applications/Firefox Nightly.app",
42
+ ],
43
+ browserNSSDBDirectoryUrls: [
44
+ new URL(
45
+ `./Library/Application Support/Firefox/Profiles/`,
46
+ assertAndNormalizeDirectoryUrl(process.env.HOME),
47
+ ),
48
+ ],
54
49
  getBrowserClosedPromise: async () => {
55
50
  if (!isFirefoxOpen()) {
56
51
  return
@@ -78,5 +73,6 @@ export const executeTrustQueryOnFirefox = ({
78
73
  }
79
74
 
80
75
  const isFirefoxOpen = () => {
81
- return execSync("ps aux").includes("firefox")
76
+ const psAux = execSync("ps aux")
77
+ return psAux.includes("Firefox.app")
82
78
  }
@@ -9,6 +9,7 @@ import { urlToFilename } from "@jsenv/urls"
9
9
  import { createDetailedMessage, UNICODE } from "@jsenv/log"
10
10
  import { assertAndNormalizeDirectoryUrl, collectFiles } from "@jsenv/filesystem"
11
11
 
12
+ import { detectBrowser } from "./browser_detection.js"
12
13
  import { exec } from "./exec.js"
13
14
  import { searchCertificateInCommandOutput } from "./search_certificate_in_command_output.js"
14
15
  import {
@@ -32,17 +33,21 @@ export const executeTrustQueryOnBrowserNSSDB = async ({
32
33
  getCertutilBinPath,
33
34
 
34
35
  browserName,
35
- detectBrowser,
36
- browserNSSDBDirectoryUrl,
36
+ browserPaths,
37
+ browserNSSDBDirectoryUrls,
37
38
  getBrowserClosedPromise,
38
39
  }) => {
39
- const browserDetected = detectBrowser({ logger })
40
+ logger.debug(`Detecting ${browserName}...`)
41
+
42
+ const browserDetected = detectBrowser(browserPaths)
40
43
  if (!browserDetected) {
44
+ logger.debug(`${UNICODE.INFO} ${browserName} not detected`)
41
45
  return {
42
46
  status: "other",
43
47
  reason: `${browserName} not detected`,
44
48
  }
45
49
  }
50
+ logger.debug(`${UNICODE.OK} ${browserName} detected`)
46
51
 
47
52
  if (verb === VERB_CHECK_TRUST && certificateIsNew) {
48
53
  logger.info(`${UNICODE.INFO} You should add certificate to ${browserName}`)
@@ -116,10 +121,17 @@ export const executeTrustQueryOnBrowserNSSDB = async ({
116
121
  }
117
122
  }
118
123
 
119
- const NSSDBFiles = await findNSSDBFiles({
120
- logger,
121
- NSSDBDirectoryUrl: browserNSSDBDirectoryUrl,
122
- })
124
+ let NSSDBFiles
125
+ for (const browserNSSDBDirectoryUrl of browserNSSDBDirectoryUrls) {
126
+ NSSDBFiles = await findNSSDBFiles({
127
+ logger,
128
+ NSSDBDirectoryUrl: browserNSSDBDirectoryUrl,
129
+ })
130
+ if (NSSDBFiles.length > 0) {
131
+ break
132
+ }
133
+ }
134
+
123
135
  const fileCount = NSSDBFiles.length
124
136
  if (fileCount === 0) {
125
137
  const reason = `could not find nss database file`
@@ -281,6 +293,7 @@ const isCertificateNotFoundError = (error) => {
281
293
 
282
294
  const NSSDirectoryCache = {}
283
295
  const findNSSDBFiles = async ({ logger, NSSDBDirectoryUrl }) => {
296
+ NSSDBDirectoryUrl = String(NSSDBDirectoryUrl)
284
297
  const resultFromCache = NSSDirectoryCache[NSSDBDirectoryUrl]
285
298
  if (resultFromCache) {
286
299
  return resultFromCache
package/src/main.js CHANGED
@@ -2,6 +2,10 @@
2
2
  * This file is the first file executed by code using the package
3
3
  * Its responsability is to export what is documented
4
4
  * Ideally this file should be kept simple to help discovering codebase progressively.
5
+ *
6
+ * see also
7
+ * - https://github.com/davewasmer/devcert
8
+ * - https://github.com/FiloSottile/mkcert
5
9
  */
6
10
 
7
11
  export {