check-installed 2.0.2 → 2.1.1

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
@@ -2,63 +2,105 @@
2
2
  Minimal Node package to check that dependencies are installed ✅
3
3
 
4
4
  [![npm](https://img.shields.io/npm/v/check-installed)](https://www.npmjs.com/package/check-installed)
5
+ [![pipeline status](https://gitlab.com/flippidippi/check-installed/badges/main/pipeline.svg)](https://gitlab.com/flippidippi/check-installed/-/pipelines?ref=main)
6
+ [![coverage report](https://gitlab.com/flippidippi/check-installed/badges/main/coverage.svg)](https://check-installed-flippidippi-09a6e441a6dd0a7a65f32f5fe3ec449245f.gitlab.io/coverage)
5
7
 
6
8
  ## Install
7
9
  ```bash
8
10
  $ npm i check-installed --save-dev
9
11
  ```
10
12
 
11
- ## Usage
12
- - Run this before npm scripts to make sure that the environment is set up correctly
13
- - It checks that engines and node modules are installed and are the correct versions
13
+ ## Checks
14
+ ### Engines Check
15
+ - Compares the installed version of engines to the versions specified in `package.json`
16
+ - Engines can be things like node, dotnet, or anything that responds to `--version`
14
17
  - Version are checked with `semver.satisfies()`, so you can use any valid semver range
15
18
  - See [semver](https://www.npmjs.com/package/semver) for more info
16
-
17
- ### Engine Check
18
- - Compares the installed version of an engine to the version specified in `package.json`
19
- - Engines can be things like node, dotnet, or anything that responds to `--version`
20
-
21
- ### Node Module Check
22
- - Compares the installed version of a node module to the version specified in `package.json`
23
- - Versions for modules that have `latest` are not checked, only that they are installed
24
- - Optional node module dependencies are only checked if they are installed
25
- - Git URL versions are skipped
26
-
27
- ## Example
28
- In `package.json`:
29
19
  ```json
30
20
  "engines": {
31
21
  "node": ">=12.x",
32
22
  "npm": ">=6",
33
23
  "dotnet": "^6.0.410"
34
24
  },
25
+ ```
26
+
27
+ ### Modules Check
28
+ - Compares the installed versions of node modules to the versions specified in `package.json`
29
+ - Versions for modules that have `latest` are not checked, only that they are installed
30
+ - Optional node module dependencies are only checked if they are installed
31
+ - Git URL versions are skipped
32
+
33
+ ## Usage
34
+
35
+ ### CLI
36
+ Run `check-installed` before npm scripts or directly to ensure that the environment is set up correctly.
37
+ If any check fails, the process will throw and exit with a non-zero exit code.
38
+
39
+ #### NPM Scripts
40
+ You can add a check script and run with `npm run check` or call it from other commands:
41
+ ```json
35
42
  "scripts": {
36
43
  "check": "check-installed",
37
- "start": "npm run check && node index.js"
44
+ "start": "npm run check && node index.js",
45
+ "test": "npm run check && jest"
38
46
  }
39
47
  ```
48
+ This repo actually uses `check-installed` directly 🤯.
40
49
 
41
- ## Options
42
- - Use `npx` to test out options like: `npx check-installed --help`
43
- - Update `package.json` to use options like:
44
- ```json
45
- "check": "check-installed --show-engines"
50
+ #### Command Line
51
+ ```bash
52
+ npx check-installed
53
+ ```
54
+
55
+ ### API
56
+ You can call the checks directly from node programatically if needed like:
57
+ ```js
58
+ const { checkEngines, checkModules } = require('check-installed')
59
+ const json = require('./package.json')
60
+
61
+ await checkEngines(json)
62
+ await checkModules(json)
63
+ await checkEngines(json, { showEngines: true })
64
+ await checkModules(json, { showSuccess: true })
46
65
  ```
66
+ Each check returns a `Promise<void>` that throws if any check fails.
67
+ They are typed to accept the entire `options` object, but only use options they need.
47
68
 
48
- #### `--help`
69
+ ### Options
70
+ - All options are optional and will be defaulted
71
+ - CLI formats to change default values:
72
+ - `boolean`:
73
+ - `true`: `--option-name` or `--option-name=true`
74
+ - `false`: `--option-name=false` or `--option-name=` or `--option-name=anythingelse`
75
+ - `string`: `--option-name=value`
76
+ - Options for `checkEngines` and `checkModules` are the same as CLI options but `camelCased`
77
+
78
+ ### `--help`
49
79
  Show help (skips check)
50
80
 
51
- #### `--skip-engines`
81
+ *Type: `boolean`, Default: `false`*
82
+
83
+ ### `--skip-engines`
52
84
  Skip checking engines
53
85
 
54
- #### `--skip-modules`
86
+ *Type: `boolean`, Default: `false`*
87
+
88
+ ### `--skip-modules`
55
89
  Skip checking node modules
56
90
 
57
- #### `--show-success`
91
+ *Type: `boolean`, Default: `false`*
92
+
93
+ ### `--show-success`
58
94
  Show success message on successful checks
59
95
 
60
- #### `--show-engines`
96
+ *Type: `boolean`, Default: `false`*
97
+
98
+ ### `--show-engines`
61
99
  Show installed engines on successful check
62
100
 
101
+ *Type: `boolean`, Default: `false`*
102
+
63
103
  ### `--show-modules`
64
104
  Show installed node modules on successful check
105
+
106
+ *Type: `boolean`, Default: `false`*
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- require("../index").cli();
2
+ require('../index').cli()
package/index.js CHANGED
@@ -1,49 +1,9 @@
1
- const { HELP, OPTIONS } = require('./lib/constants')
1
+ const { cli } = require('./lib/cli')
2
2
  const { checkEngines } = require('./lib/checkEngines')
3
3
  const { checkModules } = require('./lib/checkModules')
4
4
 
5
- /**
6
- * Get options from CLI arguments
7
- * @param {string[]} args - CLI arguments
8
- * @returns {typeof OPTIONS} - Options for the CLI with defaults
9
- */
10
- function getOptions (args) {
11
- const options = { ...OPTIONS }
12
-
13
- for (const arg of args) {
14
- if (arg.startsWith('--')) {
15
- const [key, value] = arg.slice(2).split('=')
16
- const keyCamelCase = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
17
-
18
- if (options[keyCamelCase] != null) {
19
- options[keyCamelCase] = value ?? true
20
- }
21
- }
22
- }
23
-
24
- return options
5
+ module.exports = {
6
+ cli,
7
+ checkEngines,
8
+ checkModules
25
9
  }
26
-
27
- /**
28
- * check-installed CLI entry point
29
- * @param {string[]} argv - CLI arguments
30
- */
31
- async function cli (argv = process.argv) {
32
- const args = argv.slice(2)
33
- const options = getOptions(args)
34
-
35
- if (options.help) {
36
- console.log(HELP)
37
- return
38
- }
39
-
40
- if (!options.skipEngines) {
41
- await checkEngines(options)
42
- }
43
-
44
- if (!options.skipModules) {
45
- await checkModules(options)
46
- }
47
- }
48
-
49
- exports.cli = cli
@@ -1,6 +1,6 @@
1
1
  const { spawn } = require('child_process')
2
- const { resolve } = require('path')
3
2
  const semver = require('semver')
3
+ const { OPTIONS } = require('./constants')
4
4
 
5
5
  /**
6
6
  * Get the version of an engine
@@ -51,11 +51,12 @@ async function checkEngineVersion (name, version) {
51
51
 
52
52
  /**
53
53
  * Checks engines in `package.json` are installed
54
- * @param {typeof import('./constants').OPTIONS} options - Options for the CLI
54
+ * @param {object} json - The `package.json` JSON object
55
+ * @param {Partial<typeof import('./constants').OPTIONS>} options - Options for the CLI
56
+ * @returns {Promise<void>} - Resolves when all engines are checked (throws on check fail)
55
57
  */
56
- async function checkEngines (options) {
57
- const { showSuccess, showEngines } = options
58
- const json = require(resolve(process.cwd(), 'package.json'))
58
+ async function checkEngines (json = {}, options) {
59
+ const { showSuccess, showEngines } = { ...OPTIONS, ...options }
59
60
 
60
61
  // Check engines
61
62
  const engines = await Promise.all(
@@ -1,6 +1,7 @@
1
1
  const { resolve } = require('path')
2
2
  const fs = require('fs')
3
3
  const semver = require('semver')
4
+ const { OPTIONS } = require('./constants')
4
5
 
5
6
  /**
6
7
  * Regex used to extract the real name and version from an npm alias
@@ -53,11 +54,12 @@ function checkModuleVersion (name, version, optional) {
53
54
 
54
55
  /**
55
56
  * Checks node modules in `package.json` are installed
56
- * @param {typeof import('./constants').OPTIONS} options - Options for the CLI
57
+ * @param {object} json - The `package.json` JSON object
58
+ * @param {Partial<typeof import('./constants').OPTIONS>} options - Options for the CLI
59
+ * @returns {Promise<void>} - Resolves when all modules are checked (throws on check fail)
57
60
  */
58
- async function checkModules (options) {
59
- const { showSuccess, showModules } = options
60
- const json = require(resolve(process.cwd(), 'package.json'))
61
+ async function checkModules (json = {}, options) {
62
+ const { showSuccess, showModules } = { ...OPTIONS, ...options }
61
63
 
62
64
  // Check modules
63
65
  const modules = [
package/lib/cli.js ADDED
@@ -0,0 +1,68 @@
1
+ const { resolve } = require('path')
2
+ const { HELP, OPTIONS } = require('./constants')
3
+ const { checkEngines } = require('./checkEngines')
4
+ const { checkModules } = require('./checkModules')
5
+
6
+ /**
7
+ * Get options from CLI arguments
8
+ * @param {string[]} args - CLI arguments
9
+ * @returns {typeof OPTIONS} - Options for the CLI with defaults
10
+ */
11
+ function getOptions (args) {
12
+ const options = {}
13
+
14
+ for (const arg of args) {
15
+ if (arg.startsWith('--')) {
16
+ const [key, value] = arg.slice(2).split('=')
17
+ const keyCamelCase = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
18
+ const option = OPTIONS[keyCamelCase]
19
+
20
+ // Only set if the option is defined in `OPTIONS`
21
+ if (option !== undefined) {
22
+ let newValue
23
+
24
+ // If boolean, `true` only if no value or value is "true"
25
+ // Otherwise, only if value provided
26
+ if (typeof option === 'boolean') {
27
+ newValue = value == null ? true : value === 'true'
28
+ } else if (value != null) {
29
+ newValue = value
30
+ }
31
+
32
+ // Set only if valid and not already default
33
+ if (newValue !== undefined && newValue !== option) {
34
+ options[keyCamelCase] = newValue
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ return options
41
+ }
42
+
43
+ /**
44
+ * check-installed CLI entry point
45
+ * @param {string[]} argv - CLI arguments
46
+ * @returns {Promise<void>} - Promise that resolves when the CLI is done (throws on check fail)
47
+ */
48
+ async function cli (argv = process.argv) {
49
+ const json = require(resolve(process.cwd(), 'package.json'))
50
+ const options = getOptions(argv.slice(2))
51
+
52
+ if (options.help) {
53
+ console.log(HELP)
54
+ return
55
+ }
56
+
57
+ if (!options.skipEngines) {
58
+ await checkEngines(json, options)
59
+ }
60
+
61
+ if (!options.skipModules) {
62
+ await checkModules(json, options)
63
+ }
64
+ }
65
+
66
+ module.exports = {
67
+ cli
68
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "check-installed",
3
- "version": "2.0.2",
3
+ "version": "2.1.1",
4
4
  "description": "Minimal Node package to check that dependencies are installed ✅",
5
5
  "author": "Phillip Lanclos <check-installed@flippidippi.com>",
6
6
  "license": "Unlicense",
@@ -35,7 +35,10 @@
35
35
  "check": "./bin/check-installed",
36
36
  "lint": "standard",
37
37
  "lint:fix": "npm run lint -- --fix",
38
- "test": "npm run check",
38
+ "test": "npm run check && jest",
39
+ "test:coverage": "npm run test -- --coverage",
40
+ "test:watch": "npm run test -- --watch",
41
+ "test:ci": "npm run test:coverage -- --ci --reporters=default --reporters=jest-junit",
39
42
  "prepare": "husky install"
40
43
  },
41
44
  "dependencies": {
@@ -43,6 +46,25 @@
43
46
  },
44
47
  "devDependencies": {
45
48
  "husky": "^8.0.3",
49
+ "jest": "^29.7.0",
50
+ "jest-junit": "^16.0.0",
46
51
  "standard": "^17.1.0"
52
+ },
53
+ "standard": {
54
+ "env": [
55
+ "jest"
56
+ ]
57
+ },
58
+ "jest": {
59
+ "collectCoverageFrom": [
60
+ "index.js",
61
+ "lib/**/*.js"
62
+ ],
63
+ "coverageReporters": [
64
+ "html",
65
+ "text",
66
+ "text-summary",
67
+ "cobertura"
68
+ ]
47
69
  }
48
70
  }