From 6a941ec1a5c6dd9e5ede5d70c5775fad95c1bd47 Mon Sep 17 00:00:00 2001 From: Jakub Gladykowski Date: Thu, 29 May 2025 11:40:38 -0300 Subject: [PATCH 1/4] Support monorepo and workaround local dependencies --- index.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index d90f153..53ca2d5 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,10 @@ var parse = require('spdx-expression-parse') var satisfies = require('semver').satisfies var spdxAllowed = require('spdx-whitelisted') -function licensee (configuration, path, callback) { +async function licensee (configurationOriginal, path, callback) { + // We do not want to modify original object when looping this method + configuration = structuredClone(configurationOriginal) + if (!validConfiguration(configuration)) { return callback(new Error('Invalid configuration')) } @@ -34,7 +37,7 @@ function licensee (configuration, path, callback) { callback(new Error('No licenses or packages allowed.')) } else { var arborist = new Arborist({ path }) - arborist.loadActual({ forceActual: true }) + return arborist.loadActual({ forceActual: true }) .then(function (tree) { var dependencies = Array.from(tree.inventory.values()) .filter(function (dependency) { @@ -43,7 +46,7 @@ function licensee (configuration, path, callback) { if (configuration.filterPackages) { dependencies = configuration.filterPackages(dependencies) } - callback(null, findIssues(configuration, dependencies)) + return callback(null, findIssues(configuration, dependencies)) }) .catch(function (error) { return callback(error) @@ -108,9 +111,14 @@ function findIssues (configuration, dependencies) { } }) - results.sort(function (a, b) { - return a.name.localeCompare(b.name) - }) + // Dependencies defined as file:./src/js-vendor/tablesorter will not have metadata + const noName = results.filter(x => !x.name) + + if (!noName) { + results.sort(function (a, b) { + return a.name.localeCompare(b.name) + }) + } return results } @@ -174,6 +182,11 @@ function resultForPackage (configuration, tree) { typeof ignore.author === 'string' && personMatches(result.author, ignore.author) ) return true + if ( + ignore.path && + typeof ignore.path === 'string' && + result.path.includes(ignore.path) + ) return true return false }) if (ignored) { From 7a0abd01de20c5cc6bdf7fe2c4fe90842c441766 Mon Sep 17 00:00:00 2001 From: Jakub Gladykowski Date: Mon, 2 Jun 2025 15:48:41 -0300 Subject: [PATCH 2/4] Add test data --- index.js | 2 +- .../.licensee.json | 9 +++++++++ .../symlinked/node_modules/subdependency | 1 + .../@nonexistent/symlinked/package.json | 7 +++++++ .../package.json | 7 +++++++ tests/nonexistent-symlinked-subdependency/test.js | 15 +++++++++++++++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/nonexistent-symlinked-subdependency/.licensee.json create mode 120000 tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/node_modules/subdependency create mode 100644 tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/package.json create mode 100644 tests/nonexistent-symlinked-subdependency/package.json create mode 100644 tests/nonexistent-symlinked-subdependency/test.js diff --git a/index.js b/index.js index 53ca2d5..8394d44 100644 --- a/index.js +++ b/index.js @@ -111,7 +111,7 @@ function findIssues (configuration, dependencies) { } }) - // Dependencies defined as file:./src/js-vendor/tablesorter will not have metadata + // Non existing symlinks will not have metadata const noName = results.filter(x => !x.name) if (!noName) { diff --git a/tests/nonexistent-symlinked-subdependency/.licensee.json b/tests/nonexistent-symlinked-subdependency/.licensee.json new file mode 100644 index 0000000..905b4e7 --- /dev/null +++ b/tests/nonexistent-symlinked-subdependency/.licensee.json @@ -0,0 +1,9 @@ +{ + "licenses": { + "spdx": [ + "Apache-2.0" + ] + }, + "packages": {}, + "ignore": [{ "path": "nonexistent/symlinked/node_modules/subdependency" }] +} diff --git a/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/node_modules/subdependency b/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/node_modules/subdependency new file mode 120000 index 0000000..4428094 --- /dev/null +++ b/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/node_modules/subdependency @@ -0,0 +1 @@ +../src/js-vendor/tablesorter \ No newline at end of file diff --git a/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/package.json b/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/package.json new file mode 100644 index 0000000..e0bfab4 --- /dev/null +++ b/tests/nonexistent-symlinked-subdependency/node_modules/@nonexistent/symlinked/package.json @@ -0,0 +1,7 @@ +{ + "name": "nonexistent/symlinked", + "license": "Apache-2.0", + "dependencies": { + "subdependency": "file:./not_exists" + } +} diff --git a/tests/nonexistent-symlinked-subdependency/package.json b/tests/nonexistent-symlinked-subdependency/package.json new file mode 100644 index 0000000..ed6dd65 --- /dev/null +++ b/tests/nonexistent-symlinked-subdependency/package.json @@ -0,0 +1,7 @@ +{ + "name": "nonexistent-symlinked-subdependency", + "dependencies": { + "@nonexistent/symlinked": "*" + }, + "private": true +} diff --git a/tests/nonexistent-symlinked-subdependency/test.js b/tests/nonexistent-symlinked-subdependency/test.js new file mode 100644 index 0000000..1401580 --- /dev/null +++ b/tests/nonexistent-symlinked-subdependency/test.js @@ -0,0 +1,15 @@ +var tap = require('tap') + +var results = require('../run')(['--ndjson'], __dirname) + +tap.equal(results.status, 0) + +var output = results.stdout.trim().split('\n').map(line => JSON.parse(line)) + +tap.assert( + output.some(result => result.name === 'nonexistent/symlinked' && result.approved === true) +) + +tap.assert( + output.some(result => result.version === '' && result.approved === true) +) From 9557bfb268199b89c76a6b7532d259f0e7da1829 Mon Sep 17 00:00:00 2001 From: Jakub Gladykowski Date: Mon, 9 Jun 2025 10:28:05 -0300 Subject: [PATCH 3/4] Prevent empty name exception --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index 8394d44..86577a3 100644 --- a/index.js +++ b/index.js @@ -237,6 +237,9 @@ function resultForPackage (configuration, tree) { } function startsWith (string, prefix) { + if (!string) { + return false + } return string.toLowerCase().indexOf(prefix.toLowerCase()) === 0 } From 62e9e16894ecd7754ab4bf6847227cba68bc3e62 Mon Sep 17 00:00:00 2001 From: Jakub Gladykowski Date: Mon, 9 Jun 2025 10:35:46 -0300 Subject: [PATCH 4/4] Fix unit test --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 86577a3..7de79f8 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,8 @@ var spdxAllowed = require('spdx-whitelisted') async function licensee (configurationOriginal, path, callback) { // We do not want to modify original object when looping this method - configuration = structuredClone(configurationOriginal) + // 'structuredClone' is not defined in test + var configuration = JSON.parse(JSON.stringify(configurationOriginal)) if (!validConfiguration(configuration)) { return callback(new Error('Invalid configuration'))