Skip to content

Commit 8fa2221

Browse files
committed
Merge branch 'feat-7' into alpha
2 parents a44288e + 9fa98f0 commit 8fa2221

18 files changed

+578
-63
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
**/node_modules
2-
**/package-lock.json
3-
**/npm-shrinkwrap.json
2+
/package-lock.json
3+
/npm-shrinkwrap.json
44

55
coverage.*
66
*.log*

README.md

+15-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ Prints supported Node.js versions for the package at the git URL.
2626

2727
### Options
2828

29-
* `--deps` - include the support information of all dependencies
29+
* `--deep` - when used with --deps, include indirect dependencies
30+
* `--deps` - include the support information of direct production dependencies
31+
* `--dev` - when used with --deps, include dev dependencies
3032

3133
## Usage (library)
3234

@@ -56,7 +58,9 @@ const result = await require('detect-node-support').detect(what, options);
5658

5759
### Options
5860

61+
- `deep: false` - when `true` and used `deps: true`, include indirect dependencies
5962
- `deps: false` - when `true`, include the support information of all dependencies.
63+
- `dev: false` - when `true` and used with `deps: true`, include dev dependencies
6064

6165
### Result
6266

@@ -124,7 +128,16 @@ const result = {
124128
// will contain a list of unique versions for each dependency found in the dependency tree
125129
"versions": {
126130
"dependency-A": ["0.0.10", "1.2.5"],
127-
"dependency-B": ["0.5.3", "1.0.0"]
131+
"dependency-B": ["0.5.3", "1.0.0"],
132+
"dependency-C": ["7.8.9"]
133+
},
134+
135+
// will contain a list of errors that were encountered while resolving dependency support information
136+
"errors": {
137+
"dependency-C": {
138+
// the `message` will always be either a string or `null`
139+
"message": "Failed to download some information or something"
140+
}
128141
}
129142
}
130143
}

bin/detect-node-support

+13-5
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,33 @@ const internals = {};
1212
internals.help = () => {
1313

1414
return `
15-
Usage: detect-node-support [--deps] [--json] <what>
15+
Usage: detect-node-support [--deps] [--dev] [--deep] [--json] <what>
1616
1717
<what> can be an npm package name, or a Github URL, or a path
1818
with a package.json.
1919
2020
Options:
21-
--deps Include the support information of all dependencies
21+
--deep When used with --deps, include indirect dependencies
22+
--deps Include the support information of direct production dependencies
23+
--dev When used with --deps, include direct dev dependencies
2224
--json Print JSON formatted output
2325
`;
2426
};
2527

26-
exports.main = async ({ _: [what], deps, json }) => {
28+
exports.main = async ({ _: [what], deps, deep, dev, json }) => {
2729

2830
if (!what) {
2931
console.log(internals.help());
3032
return;
3133
}
3234

33-
const result = await NodeSupport.detect(what, { deps });
35+
if (!deps && (deep || dev)) {
36+
console.log('--deep and --dev can only be used together with --deps\n');
37+
console.log(internals.help());
38+
return;
39+
}
40+
41+
const result = await NodeSupport.detect(what, { deps, deep, dev });
3442

3543
if (json) {
3644
console.log(JSON.stringify(result, null, ' '));
@@ -40,7 +48,7 @@ exports.main = async ({ _: [what], deps, json }) => {
4048
}
4149
};
4250

43-
exports.main(Minimist(process.argv.slice(2), { boolean: ['deps', 'json'] }))
51+
exports.main(Minimist(process.argv.slice(2), { boolean: ['deps', 'dev', 'deep', 'json'] }))
4452
.catch((err) => {
4553

4654
console.error(err);

lib/deps.js

+62-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
'use strict';
22

3+
const Debug = require('debug');
34
const { Arborist } = require('@npmcli/arborist');
45
const Fs = require('fs');
56
const Path = require('path');
6-
const Tempy = require('tempy');
7+
const Tmp = require('tmp');
78

89
const Package = require('./package');
10+
const Utils = require('./utils');
911

1012
const internals = {};
1113

1214

15+
internals.log = Debug('detect-node-support');
16+
17+
1318
internals.walk = (node, callback) => {
1419

1520
callback(node);
@@ -21,15 +26,29 @@ internals.walk = (node, callback) => {
2126
};
2227

2328

24-
exports.resolve = async ({ packageJson, lockfile }) => {
29+
internals.resolve = async ({ packageJson, lockfile }, options) => {
30+
31+
const { deep, dev } = options;
32+
33+
const tmpDir = Tmp.dirSync({ unsafeCleanup: true });
34+
const path = tmpDir.name;
2535

26-
const path = Tempy.directory();
2736
Fs.writeFileSync(Path.join(path, 'package.json'), JSON.stringify(packageJson, null, ' '));
2837

2938
if (lockfile) {
3039
Fs.writeFileSync(Path.join(path, 'package-lock.json'), JSON.stringify(lockfile, null, ' '));
3140
}
3241

42+
const direct = new Set();
43+
['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'].forEach((depType) => {
44+
45+
if (!packageJson[depType]) {
46+
return;
47+
}
48+
49+
Object.keys(packageJson[depType]).forEach((dep) => direct.add(dep));
50+
});
51+
3352
const arborist = new Arborist({ path });
3453

3554
await arborist.buildIdealTree();
@@ -38,11 +57,23 @@ exports.resolve = async ({ packageJson, lockfile }) => {
3857

3958
internals.walk(arborist.idealTree, (node) => {
4059

41-
if (node === arborist.idealTree) {
60+
if (node.isRoot) {
61+
return;
62+
}
63+
64+
if (!dev && node.dev) {
65+
// only include dev deps when `options.dev` flag is set
66+
return;
67+
}
68+
69+
if (!deep && !node.parent.isRoot) {
70+
// only include deep deps when `options.deep` flag is set
4271
return;
4372
}
4473

45-
if (node.dev) {
74+
if (!deep && !direct.has(node.name)) {
75+
// only include deep deps when `options.deep` flag is set
76+
// workaround for https://github.com./npm/arborist/issues/60
4677
return;
4778
}
4879

@@ -56,6 +87,8 @@ exports.resolve = async ({ packageJson, lockfile }) => {
5687
result[name] = [...map[name]];
5788
}
5889

90+
tmpDir.removeCallback();
91+
5992
return result;
6093
};
6194

@@ -71,23 +104,42 @@ internals.tryLoad = async (loadFile, filename) => {
71104
}
72105
};
73106

74-
exports.detect = async ({ packageJson, loadFile }) => {
107+
exports.detect = async ({ packageJson, loadFile }, options) => {
75108

76109
const lockfile = (await internals.tryLoad(loadFile, 'package-lock.json')) || (await internals.tryLoad(loadFile, 'npm-shrinkwrap.json'));
110+
internals.log(lockfile ? 'Lock file present' : 'Lock file missing - things will be a bit slower');
77111

78-
const versions = await exports.resolve({ packageJson, lockfile });
112+
const versions = await internals.resolve({ packageJson, lockfile }, options);
79113

80114
const support = [];
115+
const errors = {};
116+
let hasErrors = false;
117+
118+
const packages = Object.keys(versions).sort();
119+
const n = packages.length;
120+
121+
for (let i = 0; i < n; ++i) {
122+
123+
const packageName = packages[i];
124+
internals.log(`Resolving dependency ${i + 1} of ${n}: ${packageName}`);
81125

82-
for (const packageName of Object.keys(versions)) {
83126
try {
84127
const { result } = await Package.detect({ packageName });
85128
support.push(result);
86129
}
87130
catch (err) {
88-
console.warn(`Failed to detect support for ${packageName}: ${err && err.message}`);
131+
hasErrors = true;
132+
errors[packageName] = {
133+
message: Utils.getErrorMessage(err)
134+
};
89135
}
90136
}
91137

92-
return { support, versions };
138+
const result = { support, versions };
139+
140+
if (hasErrors) {
141+
result.errors = errors;
142+
}
143+
144+
return result;
93145
};

lib/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
const Deps = require('./deps');
44
const Package = require('./package');
55

6-
exports.detect = async function (what, { deps } = {}) {
6+
exports.detect = async function (what, { deps, deep, dev } = {}) {
77

88
const { result, meta } = await Package.detect(what);
99

1010
if (deps) {
11-
result.dependencies = await Deps.detect(meta);
11+
result.dependencies = await Deps.detect(meta, { deep, dev });
1212
}
1313

1414
return result;

lib/utils.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,21 @@ const SimpleGit = require('simple-git/promise');
44

55
/* $lab:coverage:off$ */
66
// this is wrapped primarily to be able to stub it
7-
exports.simpleGit = (...args) => SimpleGit(...args);
7+
exports.simpleGit = (...args) => {
8+
9+
return SimpleGit(...args);
10+
};
811
/* $lab:coverage:on$ */
12+
13+
exports.getErrorMessage = (error) => {
14+
15+
if (typeof error === 'string') {
16+
return error;
17+
}
18+
19+
if (error && error.message) {
20+
return error.message;
21+
}
22+
23+
return null;
24+
};

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@
3232
"@hapi/lab": "^22.0.0",
3333
"allow-scripts": "^1.5.2",
3434
"nock": "^12.0.1",
35-
"sinon": "^9.0.0",
36-
"tmp": "^0.1.0"
35+
"sinon": "^9.0.0"
3736
},
3837
"dependencies": {
3938
"@hapi/wreck": "^17.0.0",
40-
"@npmcli/arborist": "0.0.0-pre.13",
39+
"@npmcli/arborist": "0.0.0-pre.14",
4140
"@pkgjs/nv": "0.0.3",
41+
"debug": "^4.1.1",
4242
"git-url-parse": "^11.1.2",
4343
"js-yaml": "^3.13.1",
4444
"minimist": "^1.2.5",
4545
"pacote": "^11.1.0",
4646
"simple-git": "^1.131.0",
47-
"tempy": "^0.5.0"
47+
"tmp": "^0.1.0"
4848
}
4949
}

test/deps.js

-29
This file was deleted.

test/fixtures/deps-test-package.json

-7
This file was deleted.

test/fixtures/deps-test-lock.json renamed to test/fixtures/deps-test/npm-shrinkwrap.json

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/fixtures/deps-test/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "@pkgjs/detect-node-support-deps-test",
3+
"version": "0.0.0-development",
4+
"private": true,
5+
"dependencies": {
6+
"is-ci": "^2.0.0",
7+
"ci-info": "^1.6.0"
8+
},
9+
"devDependencies": {
10+
"debug": "^4.1.1"
11+
}
12+
}

test/fixtures/packuments/ci-info.json

+1
Large diffs are not rendered by default.

test/fixtures/packuments/debug.json

+1
Large diffs are not rendered by default.

test/fixtures/packuments/is-ci.json

+1
Large diffs are not rendered by default.

test/fixtures/packuments/ms.json

+1
Large diffs are not rendered by default.

test/fixtures/packuments/rimraf.json

+1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)