Comparing version 4.4.1 to 4.5.0
131
index.js
module.exports = licensee | ||
var licenseSatisfies = require('spdx-satisfies') | ||
var parseJSON = require('json-parse-errback') | ||
var readPackageTree = require('read-package-tree') | ||
var runParallel = require('run-parallel') | ||
var satisfies = require('semver').satisfies | ||
var simpleConcat = require('simple-concat') | ||
var spawn = require('child_process').spawn | ||
var validSPDX = require('spdx-expression-validate') | ||
@@ -14,6 +18,75 @@ | ||
} else { | ||
// Read the package tree from `node_modules`. | ||
if (configuration.productionOnly) { | ||
// In order to ignore devDependencies, we need to read: | ||
// | ||
// 1. the dependencies-only dependency graph, from | ||
// `npm ls --json --production` | ||
// | ||
// 2. the structure of `node_modules` and `package.json` | ||
// files within it, with read-package-tree. | ||
// | ||
// `npm ls` calls read-package-tree internally, but does | ||
// lots of npm-specific post-processing to produce the | ||
// dependency tree. Calling read-package-tree twice, at | ||
// the same time, is far from efficient. But it works, | ||
// and doing so helps keep this package small. | ||
runParallel({ | ||
dependencies: readDependencyList, | ||
packages: readFilesystemTree | ||
}, function (error, trees) { | ||
if (error) callback(error) | ||
else withTrees(trees.packages, trees.dependencies) | ||
}) | ||
} else { | ||
// If we are analyzing _all_ installed dependencies, | ||
// and don't care whether they're devDependencies | ||
// or not, just read `node_modules`. We don't need | ||
// the dependency graph. | ||
readFilesystemTree(function (error, packages) { | ||
if (error) callback(error) | ||
else withTrees(packages, false) | ||
}) | ||
} | ||
} | ||
function withTrees (packages, dependencies) { | ||
callback(null, findIssues( | ||
configuration, packages, dependencies, [] | ||
)) | ||
} | ||
function readDependencyList (done) { | ||
var child = spawn( | ||
'npm', ['ls', '--production', '--json'], {cwd: path} | ||
) | ||
var outputError | ||
var json | ||
simpleConcat(child.stdout, function (error, buffer) { | ||
if (error) outputError = error | ||
else json = buffer | ||
}) | ||
child.once('close', function (code) { | ||
if (code !== 0) { | ||
done(new Error('npm exited with status ' + code)) | ||
} else if (outputError) { | ||
done(outputError) | ||
} else { | ||
parseJSON(json, function (error, graph) { | ||
if (error) return done(error) | ||
if (!graph.hasOwnProperty('dependencies')) { | ||
done(new Error('cannot interpret npm ls --json output')) | ||
} else { | ||
var flattened = {} | ||
flattenDependencyTree(graph.dependencies, flattened) | ||
done(null, flattened) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
function readFilesystemTree (done) { | ||
readPackageTree(path, function (error, tree) { | ||
if (error) callback(error) | ||
else callback(null, findIssues(configuration, tree, [])) | ||
if (error) return done(error) | ||
done(null, tree.children) | ||
}) | ||
@@ -23,2 +96,23 @@ } | ||
var KEY_PREFIX = '.' | ||
function flattenDependencyTree (graph, object) { | ||
Object.keys(graph).forEach(function (name) { | ||
var node = graph[name] | ||
var version = node.version | ||
var key = KEY_PREFIX + name | ||
if ( | ||
object.hasOwnProperty(key) && | ||
object[key].indexOf(version) === -1 | ||
) { | ||
object[key].push(version) | ||
} else { | ||
object[key] = [version] | ||
} | ||
if (node.hasOwnProperty('dependencies')) { | ||
flattenDependencyTree(node.dependencies, object) | ||
} | ||
}) | ||
} | ||
function validConfiguration (configuration) { | ||
@@ -49,12 +143,15 @@ return ( | ||
function findIssues (configuration, tree, results) { | ||
var dependencies = tree.children | ||
// If there are dependencies, check license metadata. | ||
if (typeof dependencies === 'object') { | ||
dependencies.forEach(function (tree) { | ||
results.push(resultForPackage(configuration, tree)) | ||
findIssues(configuration, tree, results) | ||
if (tree.hasOwnProperty('children')) { | ||
findIssues(configuration, tree.children, results) | ||
function findIssues (configuration, children, dependencies, results) { | ||
if (Array.isArray(children)) { | ||
children.forEach(function (child) { | ||
if ( | ||
!configuration.productionOnly || | ||
appearsIn(child, dependencies) | ||
) { | ||
results.push(resultForPackage(configuration, child)) | ||
findIssues(configuration, child, dependencies, results) | ||
} | ||
if (child.children) { | ||
findIssues(configuration, child.children, dependencies, results) | ||
} | ||
}) | ||
@@ -65,2 +162,12 @@ return results | ||
function appearsIn (installed, dependencies) { | ||
var name = installed.package.name | ||
var key = KEY_PREFIX + name | ||
var version = installed.package.version | ||
return ( | ||
dependencies.hasOwnProperty(key) && | ||
dependencies[key].indexOf(version) !== -1 | ||
) | ||
} | ||
function resultForPackage (configuration, tree) { | ||
@@ -67,0 +174,0 @@ var licenseExpression = configuration.license |
{ | ||
"name": "licensee", | ||
"description": "check dependency licenses against rules", | ||
"version": "4.4.1", | ||
"version": "4.5.0", | ||
"author": "Kyle E. Mitchell <kyle@kemitchell.com> (https://kemitchell.com/)", | ||
@@ -9,4 +9,7 @@ "dependencies": { | ||
"fs-access": "^1.0.0", | ||
"json-parse-errback": "^2.0.1", | ||
"read-package-tree": "^5.1.2", | ||
"run-parallel": "^1.1.6", | ||
"semver": "^5.1.0", | ||
"simple-concat": "^1.0.0", | ||
"spdx-expression-validate": "^1.0.1", | ||
@@ -13,0 +16,0 @@ "spdx-satisfies": "^0.1.3" |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27595
196
9
1
+ Addedjson-parse-errback@^2.0.1
+ Addedrun-parallel@^1.1.6
+ Addedsimple-concat@^1.0.0
+ Addedes-abstract@1.23.3(transitive)
+ Addedjson-parse-errback@2.0.1(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedsimple-concat@1.0.1(transitive)
- Removedes-abstract@1.23.4(transitive)