detect-node-support
Advanced tools
Comparing version
'use strict'; | ||
const Debug = require('debug'); | ||
const { Arborist } = require('@npmcli/arborist'); | ||
const Fs = require('fs'); | ||
const Path = require('path'); | ||
const Tempy = require('tempy'); | ||
const Tmp = require('tmp'); | ||
const Package = require('./package'); | ||
const Utils = require('./utils'); | ||
@@ -13,2 +15,5 @@ const internals = {}; | ||
internals.log = Debug('detect-node-support'); | ||
internals.walk = (node, callback) => { | ||
@@ -25,5 +30,9 @@ | ||
exports.resolve = async ({ packageJson, lockfile }) => { | ||
internals.resolve = async ({ packageJson, lockfile }, options) => { | ||
const path = Tempy.directory(); | ||
const { deep, dev } = options; | ||
const tmpDir = Tmp.dirSync({ unsafeCleanup: true }); | ||
const path = tmpDir.name; | ||
Fs.writeFileSync(Path.join(path, 'package.json'), JSON.stringify(packageJson, null, ' ')); | ||
@@ -35,2 +44,12 @@ | ||
const direct = new Set(); | ||
['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'].forEach((depType) => { | ||
if (!packageJson[depType]) { | ||
return; | ||
} | ||
Object.keys(packageJson[depType]).forEach((dep) => direct.add(dep)); | ||
}); | ||
const arborist = new Arborist({ path }); | ||
@@ -44,10 +63,22 @@ | ||
if (node === arborist.idealTree) { | ||
if (node.isRoot) { | ||
return; | ||
} | ||
if (node.dev) { | ||
if (!dev && node.dev) { | ||
// only include dev deps when `options.dev` flag is set | ||
return; | ||
} | ||
if (!deep && !node.parent.isRoot) { | ||
// only include deep deps when `options.deep` flag is set | ||
return; | ||
} | ||
if (!deep && !direct.has(node.name)) { | ||
// only include deep deps when `options.deep` flag is set | ||
// workaround for https://github.com/npm/arborist/issues/60 | ||
return; | ||
} | ||
map[node.name] = map[node.name] || new Set(); | ||
@@ -63,2 +94,4 @@ map[node.name].add(node.package.version); | ||
tmpDir.removeCallback(); | ||
return result; | ||
@@ -79,11 +112,21 @@ }; | ||
exports.detect = async ({ packageJson, loadFile }) => { | ||
exports.detect = async ({ packageJson, loadFile }, options) => { | ||
const lockfile = (await internals.tryLoad(loadFile, 'package-lock.json')) || (await internals.tryLoad(loadFile, 'npm-shrinkwrap.json')); | ||
internals.log(lockfile ? 'Lock file present' : 'Lock file missing - things will be a bit slower'); | ||
const versions = await exports.resolve({ packageJson, lockfile }); | ||
const versions = await internals.resolve({ packageJson, lockfile }, options); | ||
const support = []; | ||
const errors = {}; | ||
let hasErrors = false; | ||
for (const packageName of Object.keys(versions)) { | ||
const packages = Object.keys(versions).sort(); | ||
const n = packages.length; | ||
for (let i = 0; i < n; ++i) { | ||
const packageName = packages[i]; | ||
internals.log(`Resolving dependency ${i + 1} of ${n}: ${packageName}`); | ||
try { | ||
@@ -94,7 +137,16 @@ const { result } = await Package.detect({ packageName }); | ||
catch (err) { | ||
console.warn(`Failed to detect support for ${packageName}: ${err && err.message}`); | ||
hasErrors = true; | ||
errors[packageName] = { | ||
message: Utils.getErrorMessage(err) | ||
}; | ||
} | ||
} | ||
return { support, versions }; | ||
const result = { support, versions }; | ||
if (hasErrors) { | ||
result.errors = errors; | ||
} | ||
return result; | ||
}; |
@@ -6,3 +6,3 @@ 'use strict'; | ||
exports.detect = async function (what, { deps } = {}) { | ||
exports.detect = async function (what, { deps, deep, dev } = {}) { | ||
@@ -12,3 +12,3 @@ const { result, meta } = await Package.detect(what); | ||
if (deps) { | ||
result.dependencies = await Deps.detect(meta); | ||
result.dependencies = await Deps.detect(meta, { deep, dev }); | ||
} | ||
@@ -15,0 +15,0 @@ |
@@ -7,3 +7,19 @@ 'use strict'; | ||
// this is wrapped primarily to be able to stub it | ||
exports.simpleGit = (...args) => SimpleGit(...args); | ||
exports.simpleGit = (...args) => { | ||
return SimpleGit(...args); | ||
}; | ||
/* $lab:coverage:on$ */ | ||
exports.getErrorMessage = (error) => { | ||
if (typeof error === 'string') { | ||
return error; | ||
} | ||
if (error && error.message) { | ||
return error.message; | ||
} | ||
return null; | ||
}; |
{ | ||
"name": "detect-node-support", | ||
"version": "1.2.0-alpha.1", | ||
"version": "1.2.0-alpha.2", | ||
"description": "List the Node.js versions supported by the package/repository", | ||
@@ -35,9 +35,9 @@ "bin": { | ||
"nock": "^12.0.1", | ||
"sinon": "^9.0.0", | ||
"tmp": "^0.1.0" | ||
"sinon": "^9.0.0" | ||
}, | ||
"dependencies": { | ||
"@hapi/wreck": "^17.0.0", | ||
"@npmcli/arborist": "0.0.0-pre.13", | ||
"@npmcli/arborist": "0.0.0-pre.14", | ||
"@pkgjs/nv": "0.0.3", | ||
"debug": "^4.1.1", | ||
"git-url-parse": "^11.1.2", | ||
@@ -48,4 +48,4 @@ "js-yaml": "^3.13.1", | ||
"simple-git": "^1.131.0", | ||
"tempy": "^0.5.0" | ||
"tmp": "^0.1.0" | ||
} | ||
} |
@@ -29,3 +29,5 @@ # detect-node-support | ||
* `--deps` - include the support information of all dependencies | ||
* `--deep` - when used with --deps, include indirect dependencies | ||
* `--deps` - include the support information of direct production dependencies | ||
* `--dev` - when used with --deps, include dev dependencies | ||
@@ -60,3 +62,5 @@ ## Usage (library) | ||
- `deep: false` - when `true` and used `deps: true`, include indirect dependencies | ||
- `deps: false` - when `true`, include the support information of all dependencies. | ||
- `dev: false` - when `true` and used with `deps: true`, include dev dependencies | ||
@@ -129,3 +133,12 @@ ### Result | ||
"dependency-A": ["0.0.10", "1.2.5"], | ||
"dependency-B": ["0.5.3", "1.0.0"] | ||
"dependency-B": ["0.5.3", "1.0.0"], | ||
"dependency-C": ["7.8.9"] | ||
}, | ||
// will contain a list of errors that were encountered while resolving dependency support information | ||
"errors": { | ||
"dependency-C": { | ||
// the `message` will always be either a string or `null` | ||
"message": "Failed to download some information or something" | ||
} | ||
} | ||
@@ -132,0 +145,0 @@ } |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
NPM Shrinkwrap
Supply chain riskPackage contains a shrinkwrap file. This may allow the package to bypass normal install procedures.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
5
-16.67%145
9.85%0
-100%19691
-96.09%10
11.11%10
-9.09%354
-97.13%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed