Skip to content

Commit

Permalink
feat: include private self dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
mjeanroy committed Jun 21, 2024
1 parent 03112e9 commit 1401f5d
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 88 deletions.
5 changes: 4 additions & 1 deletion src/dependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ export class Dependency {
* Create new dependency from package description.
*
* @param {Object} pkg Package description.
* @param {boolean} self If the package is the "self" package.
* @constructor
*/
constructor(pkg) {
constructor(pkg, self) {
this.self = self || false;

this.name = pkg.name || null;
this.maintainers = pkg.maintainers || [];
this.version = pkg.version || null;
Expand Down
40 changes: 29 additions & 11 deletions src/license-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ class LicensePlugin {
this.debug(`iterative over directory tree, starting with: ${dir}`);

while (dir) {
if (!includeSelf && dir === this._cwd) {
const isSelf = dir === this._cwd;
if (isSelf && !includeSelf) {
// No need to scan "self" if it's not explicitly allowed.
break;
}
Expand All @@ -172,7 +173,7 @@ class LicensePlugin {
pkg = this._cache.get(dir);
if (pkg) {
this.debug(`found package.json in cache (package: ${pkg.name})`);
this.addDependency(pkg);
this.addDependency(pkg, isSelf);
}

break;
Expand Down Expand Up @@ -215,14 +216,14 @@ class LicensePlugin {
}

// Add the new dependency to the set of third-party dependencies.
this.addDependency(pkg);
this.addDependency(pkg, isSelf);

// We can stop now.
break;
}
}

if (dir === this._cwd) {
if (isSelf) {
// If "self" has been scanned, no need to go up in the directory tree.
break;
}
Expand Down Expand Up @@ -295,9 +296,10 @@ class LicensePlugin {
* Add new dependency to the bundle descriptor.
*
* @param {Object} pkg Dependency package information.
* @param {boolean} self If the package is the "self" package.
* @return {void}
*/
addDependency(pkg) {
addDependency(pkg, self) {
const name = pkg.name || '';
if (!name) {
this.warn('Trying to add dependency without any name, skipping it.');
Expand All @@ -307,7 +309,7 @@ class LicensePlugin {
const version = pkg.version || '';
const key = this._options.thirdParty?.multipleVersions ? `${name}@${version}` : name;
if (!this._dependencies.has(key)) {
this._dependencies.set(key, new Dependency(pkg));
this._dependencies.set(key, new Dependency(pkg, self));
}
}

Expand All @@ -325,9 +327,18 @@ class LicensePlugin {
}

const includePrivate = thirdParty.includePrivate || false;
const outputDependencies = [...this._dependencies.values()].filter((dependency) => (
includePrivate || !dependency.private
));
const includeSelf = thirdParty.includeSelf || false;
const outputDependencies = [...this._dependencies.values()].filter((dependency) => {
if (dependency.self && includeSelf) {
return true;
}

if (!dependency.private) {
return true;
}

return includePrivate;
});

if (_.isFunction(thirdParty)) {
thirdParty(outputDependencies);
Expand Down Expand Up @@ -459,7 +470,7 @@ class LicensePlugin {
/**
* Scan for dependency violations and print a warning if some violations are found.
*
* @param {Array<Object>} outputDependencies The dependencies to scan.
* @param {Array<Dependency>} outputDependencies The dependencies to scan.
* @param {string} allow The allowed licenses as a SPDX pattern.
* @return {void}
*/
Expand All @@ -472,11 +483,18 @@ class LicensePlugin {
/**
* Scan dependency for a dependency violation.
*
* @param {Object} dependency The dependency to scan.
* @param {Dependency} dependency The dependency to scan.
* @param {string|function|object} allow The allowed licenses as a SPDX pattern, or a validator function.
* @return {void}
*/
_scanLicenseViolation(dependency, allow) {
if (dependency.self) {
// Do not validate license for the "self" package.
// It's likely this package will use a private/proprietary license, and we only want to detect
// violations for third party dependencies.
return;
}

const testFn = _.isString(allow) || _.isFunction(allow) ? allow : allow.test;
const isValid = _.isFunction(testFn) ? testFn(dependency) : licenseValidator.isValid(dependency, testFn);
if (!isValid) {
Expand Down
40 changes: 27 additions & 13 deletions test/dependency.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { join } from './utils/join';

describe('Dependency', () => {
it('should extract package fields', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -52,9 +53,10 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency).toEqual({
self: false,
name: 'foo',
version: '1.0.0',
license: 'MIT',
Expand Down Expand Up @@ -89,6 +91,7 @@ describe('Dependency', () => {
});

it('should parse author field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -97,7 +100,7 @@ describe('Dependency', () => {
author: 'Mickael Jeanroy <mickael.jeanroy@gmail.com> (https://mjeanroy.com)',
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.author).toEqual({
name: 'Mickael Jeanroy',
Expand All @@ -107,6 +110,7 @@ describe('Dependency', () => {
});

it('should parse contributors field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -117,7 +121,7 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.contributors.length).toBe(1);
expect(dependency.contributors[0]).toEqual({
Expand All @@ -128,6 +132,7 @@ describe('Dependency', () => {
});

it('should parse deprecated licenses field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -138,20 +143,21 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.licenses).not.toBeDefined();
expect(dependency.license).toBe('(MIT OR Apache 2.0)');
});

it('should format dependency with name, version, and license fields', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
license: 'MIT',
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -162,14 +168,15 @@ describe('Dependency', () => {
});

it('should format dependency with optional description fied', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
license: 'MIT',
description: 'Desc',
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -181,6 +188,7 @@ describe('Dependency', () => {
});

it('should format dependency with optional author field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -191,7 +199,7 @@ describe('Dependency', () => {
},
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -203,6 +211,7 @@ describe('Dependency', () => {
});

it('should format dependency with optional repository field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -213,7 +222,7 @@ describe('Dependency', () => {
},
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -225,14 +234,15 @@ describe('Dependency', () => {
});

it('should format dependency with optional homepage field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
license: 'MIT',
homepage: 'https://github.com/mjeanroy',
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -244,6 +254,7 @@ describe('Dependency', () => {
});

it('should format dependency with optional contributors field', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -254,7 +265,7 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -268,6 +279,7 @@ describe('Dependency', () => {
});

it('should format dependency with all optional fields', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -282,7 +294,7 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -300,6 +312,7 @@ describe('Dependency', () => {
});

it('should format dependency with license text', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -326,7 +339,7 @@ describe('Dependency', () => {
],
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand All @@ -348,6 +361,7 @@ describe('Dependency', () => {
});

it('should format dependency with notice text', () => {
const self = false;
const pkg = {
name: 'foo',
version: '1.0.0',
Expand All @@ -358,7 +372,7 @@ describe('Dependency', () => {
homepage: 'https://github.com/mjeanroy',
};

const dependency = new Dependency(pkg);
const dependency = new Dependency(pkg, self);

expect(dependency.text()).toEqual(join([
`Name: ${pkg.name}`,
Expand Down
Loading

0 comments on commit 1401f5d

Please sign in to comment.