license-report
Advanced tools
Comparing version 5.0.2 to 6.0.0
@@ -5,2 +5,36 @@ # Changelog | ||
## [6.0.0](https://github.com/ironSource/license-report/compare/v5.1.0...v6.0.0) (2022-07-07) | ||
### ⚠ BREAKING CHANGES | ||
* update 'got' to v12; this requires switching to esm | ||
modules and dropping support for node versions prior to Node v14 (which | ||
are all out of maintenance status by now). | ||
* get the installed version, the author and the | ||
license type from the node_modules directory instead of from | ||
the package-lock.json file. | ||
### Bug Fixes | ||
* add default request timeout ([fce9e05](https://github.com/ironSource/license-report/commit/fce9e051170711f680aba53e3f23003a1300af39)) | ||
* add missing fieldnames in command line help text ([d29c8a1](https://github.com/ironSource/license-report/commit/d29c8a1ebf0da0c058fb0d70c47ce2f6ab290f0a)) | ||
* return 'n/a' when no license property is found in repository data ([1ffe505](https://github.com/ironSource/license-report/commit/1ffe5055086e67646f6f1d0d9f5b9667d3564bd3)) | ||
## [5.1.0](https://github.com/ironSource/license-report/compare/v5.0.2...v5.1.0) (2022-06-04) | ||
### Features | ||
* add support for installedFrom field ([207f167](https://github.com/ironSource/license-report/commit/207f167b4492e45f34a8554f026cdb5c97e4888b)) | ||
### Bug Fixes | ||
* add error handling for requests to the registry ([cb7123a](https://github.com/ironSource/license-report/commit/cb7123a055238827ed3a4d71cadff9de60e42156)), closes [#85](https://github.com/ironSource/license-report/issues/85) | ||
* fix broken e2e tests due to changed ownership for debug-js ([25d754e](https://github.com/ironSource/license-report/commit/25d754ed342b94af01b5bc96a5692495d8d687ce)) | ||
* fix missing variable declaration ([f4a64eb](https://github.com/ironSource/license-report/commit/f4a64eb5db57e42908dacb4148f93c5be7757207)) | ||
* remove typo in error message ([2cd5475](https://github.com/ironSource/license-report/commit/2cd547517af40b4f1b72b458c6f7d8be7218c6bf)) | ||
### [5.0.2](https://github.com/ironSource/license-report/compare/v5.0.1...v5.0.2) (2022-03-11) | ||
@@ -7,0 +41,0 @@ |
43
index.js
#!/usr/bin/env node | ||
const fs = require('fs') | ||
const path = require('path') | ||
const debug = require('debug')('license-report') | ||
const config = require('./lib/config.js') | ||
const getFormatter = require('./lib/getFormatter') | ||
const getInstalledVersions = require('./lib/getInstalledVersions') | ||
const addPackagesToIndex = require('./lib/addPackagesToIndex') | ||
const getPackageReportData = require('./lib/getPackageReportData.js') | ||
const packageDataToReportData = require('./lib/packageDataToReportData') | ||
const util = require('./lib/util'); | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import createDebugMessages from 'debug'; | ||
import config from './lib/config.js'; | ||
import getFormatter from './lib/getFormatter.js'; | ||
import addLocalPackageData from './lib/addLocalPackageData.js'; | ||
import addPackagesToIndex from './lib/addPackagesToIndex.js'; | ||
import addPackageDataFromRepository from './lib/addPackageDataFromRepository.js'; | ||
import packageDataToReportData from './lib/packageDataToReportData.js'; | ||
import util from './lib/util.js'; | ||
const debug = createDebugMessages('license-report'); | ||
(async () => { | ||
@@ -71,20 +73,11 @@ if (config.help) { | ||
// package-lock.json is used to get the installed versions from | ||
let installedVersions = {} | ||
const resolvedPackageLockJson = path.resolve(path.dirname(resolvedPackageJson), 'package-lock.json') | ||
debug('loading %s', resolvedPackageLockJson) | ||
if (fs.existsSync(resolvedPackageLockJson)) { | ||
const packageLockContent = await util.readJson(resolvedPackageLockJson) | ||
installedVersions = getInstalledVersions(packageLockContent, depsIndex) | ||
} else { | ||
console.warn(`Warning: the file '${resolvedPackageLockJson}' is required to get installed versions of packages`) | ||
} | ||
const results = await Promise.all( | ||
depsIndex.map(async (packageEntry) => { | ||
return await getPackageReportData(packageEntry, installedVersions) | ||
const projectRootPath = path.dirname(resolvedPackageJson) | ||
const packagesData = await Promise.all( | ||
depsIndex.map(async (element) => { | ||
const localDataForPackages = await addLocalPackageData(element, projectRootPath) | ||
const packagesData = await addPackageDataFromRepository(localDataForPackages) | ||
return packageDataToReportData(packagesData, config) | ||
}) | ||
) | ||
packagesData = results.map(element => packageDataToReportData(element, config)) | ||
console.log(outputFormatter(packagesData, config)) | ||
@@ -91,0 +84,0 @@ } catch (e) { |
@@ -1,6 +0,8 @@ | ||
/* | ||
add all packages to a package index array. | ||
maintaining uniqueness (crudely) | ||
*/ | ||
module.exports = function(packages, packageIndex, exclusions) { | ||
/** | ||
* Add all packages to a package index array maintaining uniqueness (crudely) | ||
* @param {object} packages - element from package.json (e.g. 'dependencies' or 'devDependencies') | ||
* @param {[object]} packageIndex - array containing the entries for packages ('package index') | ||
* @param {[object]} exclusions - exclusions list from config | ||
*/ | ||
function addPackagesToIndex(packages, packageIndex, exclusions) { | ||
exclusions = exclusions || [] | ||
@@ -48,2 +50,4 @@ | ||
} | ||
} | ||
} | ||
export default addPackagesToIndex; |
@@ -1,6 +0,8 @@ | ||
const rc = require('rc') | ||
const path = require('path') | ||
import path from 'node:path'; | ||
import url from 'node:url'; | ||
import rc from 'rc'; | ||
module.exports = rc('license-report', { | ||
const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); | ||
export default rc('license-report', { | ||
/* | ||
@@ -100,2 +102,6 @@ possible outputs: | ||
}, | ||
installedFrom: { | ||
value: 'n/a', | ||
label: 'installed from' | ||
}, | ||
remoteVersion: { | ||
@@ -122,4 +128,7 @@ value: '', | ||
httpRetryOptions: { | ||
maxAttempts: 5 | ||
limit: 5 | ||
}, | ||
httpTimeoutOptions: { | ||
request: 30000 | ||
} | ||
}) | ||
}) |
@@ -1,26 +0,39 @@ | ||
module.exports = function(json) { | ||
/** | ||
* Extract license type from content of a package.json file | ||
* @param {object} packageJSONContent - content of package.json for 1 package | ||
* @returns {string} with license type | ||
*/ | ||
function extractLicense(packageJSONContent) { | ||
const notAvailableText = 'n/a' | ||
if (typeof json.license === 'string') { | ||
return json.license | ||
if (typeof packageJSONContent.license === 'string') { | ||
return packageJSONContent.license | ||
} | ||
if (typeof json.license === 'object') { | ||
return json.license.type | ||
if (typeof packageJSONContent.license === 'object') { | ||
return packageJSONContent.license.type | ||
} | ||
if (Array.isArray(json.licenses)) { | ||
let result = '' | ||
for (let i = 0; i < json.licenses.length; i++) { | ||
let licenseType | ||
if (Array.isArray(packageJSONContent.licenses)) { | ||
licenseType = '' | ||
for (let i = 0; i < packageJSONContent.licenses.length; i++) { | ||
if (i > 0) | ||
result += ', ' | ||
licenseType += ', ' | ||
if (typeof json.licenses[i] === 'string') { | ||
result += json.licenses[i] | ||
if (typeof packageJSONContent.licenses[i] === 'string') { | ||
licenseType += packageJSONContent.licenses[i] | ||
} else { | ||
result += json.licenses[i].type | ||
licenseType += packageJSONContent.licenses[i].type | ||
} | ||
} | ||
if (licenseType.length === 0) { | ||
licenseType = notAvailableText | ||
} | ||
} else { | ||
licenseType = notAvailableText | ||
} | ||
return licenseType | ||
} | ||
return result | ||
} | ||
} | ||
export default extractLicense; |
@@ -1,4 +0,9 @@ | ||
const visit = require('visit-values') | ||
import visit from 'visit-values'; | ||
module.exports = function(json) { | ||
/** | ||
* Extract link to repository from registry data for a package | ||
* @param {object} json - object fetched from registry with information about 1 package | ||
* @returns {string} with link to repository | ||
*/ | ||
function extractLink(json) { | ||
if (json.repository && json.repository.url) { | ||
@@ -27,2 +32,4 @@ return json.repository.url | ||
} | ||
} | ||
} | ||
export default extractLink; |
@@ -1,7 +0,5 @@ | ||
const table = require('text-table') | ||
const tableify = require('@kessler/tableify') | ||
const fs = require('fs') | ||
import fs from 'node:fs'; | ||
import table from 'text-table'; | ||
import tableify from '@kessler/tableify'; | ||
module.exports = getFormatter | ||
/** | ||
@@ -65,4 +63,4 @@ * Formats package information as json string. | ||
for (const element of data) { | ||
validatedFields = element.map(fieldValue => { | ||
validatedField = fieldValue | ||
const validatedFields = element.map(fieldValue => { | ||
let validatedField = fieldValue | ||
if (fieldValue.includes(delimiter)) { | ||
@@ -186,2 +184,4 @@ console.warn(`Warning: field contains delimiter; value: "${fieldValue}"`) | ||
return emptyRow | ||
} | ||
} | ||
export default getFormatter; |
@@ -1,7 +0,5 @@ | ||
module.exports = packageDataToReportData | ||
/** | ||
* Add fields from config.fields to object with information about one package. | ||
* Create object with all fields listed in config.fields with current values about one package. | ||
* Only fields from field list will be returned in generated object. | ||
* @param packageData - object with information about one package (default fields 'name', 'licenseType', 'link', 'remoteVersion', 'installedVersion', 'author') | ||
* @param packageData - object with information about one package (fields are e.g. 'name', 'licenseType', 'link', 'remoteVersion', 'installedVersion', 'author') | ||
* @param config - global configuration object | ||
@@ -23,2 +21,4 @@ * @returns object with all fields listed in config.fields | ||
return finalData | ||
} | ||
} | ||
export default packageDataToReportData; |
@@ -1,5 +0,3 @@ | ||
const fs = require('fs') | ||
import fs from 'node:fs'; | ||
exports.readJson = readJson | ||
/** | ||
@@ -15,3 +13,3 @@ * Get an object by asynchronously reading a file | ||
exports.helpText = `Generate a detailed report of the licenses of all projects dependencies. | ||
const helpText = `Generate a detailed report of the licenses of all projects dependencies. | ||
@@ -39,6 +37,11 @@ Usage: license-report [options] | ||
department, relatedTo, name, licensePeriod, material, licenseType, | ||
link, comment, installedVersion, author. | ||
link, remoteVersion, installedVersion, definedVersion, author, installedFrom. | ||
--<field>.value=<new-value> Set value for static output field. Allowed field names are: | ||
department, relatedTo, licensePeriod, material. | ||
` | ||
` | ||
export default { | ||
readJson, | ||
helpText | ||
}; |
{ | ||
"name": "license-report", | ||
"version": "5.0.2", | ||
"version": "6.0.0", | ||
"description": "creates a short report about project's dependencies (license, url etc)", | ||
@@ -10,3 +10,3 @@ "main": "index.js", | ||
"lint-commits": "commitlint --from 59f5e4b90d2d --to HEAD --verbose", | ||
"activate-commitlint": "npx husky install" | ||
"activate-commitlint": "npx husky install && npx husky add .husky/commit-msg \"npx --no -- commitlint --edit $1\"" | ||
}, | ||
@@ -16,2 +16,3 @@ "bin": { | ||
}, | ||
"type": "module", | ||
"repository": { | ||
@@ -29,7 +30,7 @@ "type": "git", | ||
"@kessler/tableify": "^1.0.2", | ||
"debug": "^4.3.3", | ||
"debug": "^4.3.4", | ||
"eol": "^0.9.1", | ||
"got": "^11.8.3", | ||
"got": "^12.1.0", | ||
"rc": "^1.2.8", | ||
"semver": "^7.3.5", | ||
"semver": "^7.3.7", | ||
"text-table": "^0.2.0", | ||
@@ -39,12 +40,12 @@ "visit-values": "^2.0.0" | ||
"devDependencies": { | ||
"@commitlint/cli": "^16.2.1", | ||
"@commitlint/config-conventional": "^16.2.1", | ||
"husky": "^7.0.4", | ||
"mocha": "^9.2.1", | ||
"nock": "^13.2.4", | ||
"standard-version": "^9.3.2" | ||
"@commitlint/cli": "^17.0.3", | ||
"@commitlint/config-conventional": "^17.0.3", | ||
"husky": "^8.0.1", | ||
"mocha": "^10.0.0", | ||
"nock": "^13.2.8", | ||
"standard-version": "^9.5.0" | ||
}, | ||
"engines": { | ||
"node": ">=7.6" | ||
"node": ">=14" | ||
} | ||
} |
# license report tool | ||
![Version](https://img.shields.io/badge/version-5.0.2-blue.svg?cacheSeconds=2592000) | ||
![Version](https://img.shields.io/badge/version-6.0.0-blue.svg?cacheSeconds=2592000) | ||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE) | ||
@@ -12,3 +12,4 @@ | ||
## Functionality | ||
`license-report` reads data from a `package.json` file and adds detailed version information about the installed versions from the corresponding `package-lock.json` file and about the latest available version from the (npm) registry. | ||
`license-report` gets the dependencies of a program or package from its `package.json` file and for each dependency adds the installed version, the license type and the author from the corresponding `package.json` file in the `node_modules` directory and the latest available version and other data from the (npm) registry where this package was installed from. | ||
As a prerequisite, the dependencies must be installed so that the node_modules directory exists in the path of the `package.json` file. | ||
@@ -93,4 +94,15 @@ ## Usage | ||
#### select fields for output: | ||
If only a few fields are required in the output, the easiest way of selecting the fields is via --fields command line arguments. | ||
There must be at least 2 --fields options, otherwise license-report | ||
will throw an error. | ||
``` | ||
# set options with command line options and config file | ||
# set options with command line arguments | ||
license-report --output=csv --fields=name --fields=installedVersion | ||
``` | ||
If more fields are needed, the best way is to use a custom config file, that contains a fields array. | ||
``` | ||
# set options with command line option for custom (partial) config file | ||
license-report --output=csv --config license-report-config.json | ||
@@ -133,2 +145,3 @@ ``` | ||
| link | link | link to the repository of the package | | ||
| installedFrom | installed from | the download source for the installed package (optional field) | | ||
| remoteVersion | remote version | latest available version of the package (can be different from the installed version) | | ||
@@ -135,0 +148,0 @@ | installedVersion | installed version | installed version of the package (can be different from the remote version) | |
@@ -1,21 +0,9 @@ | ||
const assert = require('assert') | ||
const addPackagesToIndex = require('../lib/addPackagesToIndex.js') | ||
import assert from 'node:assert'; | ||
import addPackagesToIndex from '../lib/addPackagesToIndex.js'; | ||
describe('addPackagesToIndex', function() { | ||
let index, packages | ||
let index | ||
beforeEach(function() { | ||
index = [] | ||
packages = { | ||
"@kessler/exponential-backoff": "^2.0.0", | ||
"async": "^0.9.0", | ||
"debug": "^3.1.0", | ||
"lodash": "^4.17.11", | ||
"rc": "^1.2.8", | ||
"request": "^2.88.0", | ||
"semver": "^5.4.1", | ||
"stubborn": "^1.2.5", | ||
"text-table": "^0.2.0", | ||
"visit-values": "^1.0.1" | ||
} | ||
}) | ||
@@ -35,2 +23,8 @@ | ||
it('adds a local package to the index', function() { | ||
addPackagesToIndex({ "my-local-package": "file:local-libs/my-local-package" }, index) | ||
assert.deepStrictEqual(index, [{ fullName: 'my-local-package', name: 'my-local-package', version: 'file:local-libs/my-local-package', scope: undefined, alias: '' }]) | ||
}) | ||
it('does not add duplicate packages, same package is a package that has the same name, version expression and scope', function() { | ||
@@ -64,6 +58,6 @@ addPackagesToIndex({ "@bar/foo": "*" }, index) | ||
it('add package with alias to the index', function() { | ||
addPackagesToIndex({ "mocha_8.3.1": "npm:mocha@^8.3.1" }, index) | ||
addPackagesToIndex({ "my-mocha": "npm:mocha@^8.3.1" }, index) | ||
assert.deepStrictEqual(index, [{ fullName: 'mocha', name: 'mocha', version: '^8.3.1', scope: undefined, alias: 'mocha_8.3.1' }]) | ||
}); | ||
assert.deepStrictEqual(index, [{ fullName: 'mocha', name: 'mocha', version: '^8.3.1', scope: undefined, alias: 'my-mocha' }]) | ||
}) | ||
@@ -74,3 +68,3 @@ it('add scoped package with alias to the index', function() { | ||
assert.deepStrictEqual(index, [{ fullName: '@kessler/tableify', name: 'tableify', version: '^1.0.1', scope: 'kessler', alias: '@kessler/tableify_1.0.1' }]) | ||
}); | ||
}) | ||
}) |
@@ -1,9 +0,12 @@ | ||
const cp = require('child_process') | ||
const util = require('util'); | ||
const path = require('path') | ||
const assert = require('assert') | ||
const fs = require('fs') | ||
const eol = require('eol') | ||
const expectedOutput = require('./fixture/expectedOutput.js') | ||
import assert from 'node:assert'; | ||
import cp from 'node:child_process'; | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import url from 'node:url'; | ||
import util from 'node:util'; | ||
import eol from 'eol'; | ||
import expectedOutput from './fixture/expectedOutput.js'; | ||
const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); | ||
const scriptPath = path | ||
@@ -13,20 +16,37 @@ .resolve(__dirname, '..', 'index.js') | ||
const packagePath = path | ||
.resolve(__dirname, 'fixture', 'packageForE2eTest.json') | ||
// test data for e2e test using the default fields | ||
const defaultFieldsPackageJsonPath = path | ||
.resolve(__dirname, 'fixture', 'default-fields', 'package.json') | ||
.replace(/(\s+)/g, '\\$1') | ||
const execAsPromise = util.promisify(cp.exec); | ||
// test data for e2e test using all fields | ||
const allFieldsPackageJsonPath = path | ||
.resolve(__dirname, 'fixture', 'all-fields', 'package.json') | ||
.replace(/(\s+)/g, '\\$1') | ||
const allFieldsConfigPath = path | ||
.resolve(__dirname, 'fixture', 'all-fields', 'license-report-config.json') | ||
.replace(/(\s+)/g, '\\$1') | ||
// test data for e2e test using the default fields and local packages | ||
const localPackagesPackageJsonPath = path | ||
.resolve(__dirname, 'fixture', 'local-packages', 'package.json') | ||
.replace(/(\s+)/g, '\\$1') | ||
const localPackagesConfigPath = path | ||
.resolve(__dirname, 'fixture', 'local-packages', 'license-report-config.json') | ||
.replace(/(\s+)/g, '\\$1') | ||
const execAsPromise = util.promisify(cp.exec) | ||
let expectedData | ||
describe('end to end test', function() { | ||
describe('end to end test for default fields', function() { | ||
this.timeout(50000) | ||
beforeEach(async () => { | ||
expectedData = EXPECTED_RAW_DATA.slice(0) | ||
await expectedOutput.addVersionToExpectedData(expectedData) | ||
expectedData = EXPECTED_DEFAULT_FIELDS_RAW_DATA.slice(0) | ||
await expectedOutput.addRemoteVersionsToExpectedData(expectedData) | ||
}) | ||
it('produce a json report', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath}`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath}`) | ||
const result = JSON.parse(stdout) | ||
@@ -36,20 +56,23 @@ const expectedJsonResult = expectedOutput.rawDataToJson(expectedData) | ||
assert.deepStrictEqual(result, expectedJsonResult) | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
it('produce a table report', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --output=table`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath} --output=table`) | ||
const expectedTableResult = expectedOutput.rawDataToTable(expectedData, EXPECTED_TABLE_TEMPLATE) | ||
assert.strictEqual(stdout, expectedTableResult) | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
it('produce a csv report', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --output=csv --csvHeaders`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath} --output=csv --csvHeaders`) | ||
const expectedCsvResult = expectedOutput.rawDataToCsv(expectedData, EXPECTED_CSV_TEMPLATE) | ||
assert.strictEqual(stdout, expectedCsvResult) | ||
assert.strictEqual(stderr, 'Warning: field contains delimiter; value: \"Dan VerWeire, Yaniv Kessler\"\n') | ||
}) | ||
it('produce an html report', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --output=html`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath} --output=html`) | ||
const actualResult = eol.auto(stdout) | ||
@@ -60,41 +83,79 @@ const expectedHtmlTemplate = eol.auto(fs.readFileSync(path.join(__dirname, 'fixture', 'expectedOutput.e2e.html'), 'utf8')) | ||
assert.strictEqual(actualResult, expectedHtmlResult) | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
}) | ||
describe('end to end test for configuration', function () { | ||
describe('end to end test for local packages', function() { | ||
this.timeout(50000) | ||
beforeEach(async () => { | ||
expectedData = EXPECTED_LOCAL_PACKAGES_RAW_DATA.slice(0) | ||
await expectedOutput.addRemoteVersionsToExpectedData(expectedData) | ||
}) | ||
it('produce a json report', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${localPackagesPackageJsonPath} --config=${localPackagesConfigPath}`) | ||
const result = JSON.parse(stdout) | ||
const expectedJsonResult = expectedOutput.rawDataToJson(expectedData) | ||
assert.deepStrictEqual(result, expectedJsonResult) | ||
}) | ||
}) | ||
describe('end to end test for all fields', function() { | ||
this.timeout(50000) | ||
it('produce a json report with the fields specified in config', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${allFieldsPackageJsonPath} --config=${allFieldsConfigPath}`) | ||
const result = JSON.parse(stdout) | ||
const expectedResult = [{ | ||
department: "kessler", | ||
relatedTo: "stuff", | ||
name: "semver", | ||
licensePeriod: "perpetual", | ||
material: "material", | ||
licenseType: "ISC", | ||
link: "git+https://github.com/npm/node-semver.git", | ||
installedFrom: "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", | ||
remoteVersion: "5.7.1", | ||
installedVersion: "5.4.1", | ||
definedVersion: "^5.0.0", | ||
author:"GitHub Inc." | ||
}]; | ||
await expectedOutput.addRemoteVersionsToExpectedData(expectedResult) | ||
assert.deepStrictEqual(result, expectedResult, `expected the output to contain all the configured fields`) | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
it('produce a json report without option "only"', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${packagePath}`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath}`) | ||
const result = JSON.parse(stdout) | ||
const expectedLengthOfResult = 11 | ||
const expectedWarning = stderr.includes(`package-lock.json' is required to get installed versions of packages`) | ||
const expectedLengthOfResult = 4 | ||
assert.strictEqual(result.length, expectedLengthOfResult, `expected the list to contain ${expectedLengthOfResult} elements`) | ||
assert.strictEqual(expectedWarning, true, 'expected a warning about a missing package-lock file') | ||
}); | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
it('produce a json report with option "only=prod"', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${packagePath} --only=prod`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath} --only=prod`) | ||
const result = JSON.parse(stdout) | ||
const expectedLengthOfResult = 5 | ||
const expectedWarning = stderr.includes(`package-lock.json' is required to get installed versions of packages`) | ||
const expectedLengthOfResult = 1 | ||
assert.strictEqual(result.length, expectedLengthOfResult, `expected the list to contain ${expectedLengthOfResult} elements`) | ||
assert.strictEqual(expectedWarning, true, 'expected a warning about a missing package-lock file') | ||
}); | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
it('produce a json report with option "only=prod,opt,peer"', async () => { | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${packagePath} --only=prod,opt,peer`) | ||
const { stdout, stderr } = await execAsPromise(`node ${scriptPath} --package=${defaultFieldsPackageJsonPath} --only=prod,opt,peer`) | ||
const result = JSON.parse(stdout) | ||
const expectedLengthOfResult = 10 | ||
const expectedWarning = stderr.includes(`package-lock.json' is required to get installed versions of packages`) | ||
const expectedLengthOfResult = 3 | ||
assert.strictEqual(result.length, expectedLengthOfResult, `expected the list to contain ${expectedLengthOfResult} elements`) | ||
assert.strictEqual(expectedWarning, true, 'expected a warning about a missing package-lock file') | ||
}); | ||
}); | ||
assert.strictEqual(stderr, '', 'expected no warnings') | ||
}) | ||
}) | ||
// raw data we use to generate the expected results | ||
const EXPECTED_RAW_DATA = [ | ||
// raw data we use to generate the expected results for default fields test | ||
const EXPECTED_DEFAULT_FIELDS_RAW_DATA = [ | ||
{ | ||
@@ -110,61 +171,35 @@ author: 'Dan VerWeire, Yaniv Kessler', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
installedVersion: '1.0.2', | ||
definedVersion: '^1.0.2' | ||
}, | ||
{ | ||
author: 'TJ Holowaychuk tj@vision-media.ca', | ||
author: 'TJ Holowaychuk <tj@vision-media.ca>', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'debug', | ||
name: 'mocha', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git://github.com/debug-js/debug.git', | ||
link: 'git+https://github.com/mochajs/mocha.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: 'Ryan Van Etten', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'eol', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/ryanve/eol.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
installedVersion: '9.1.2', | ||
definedVersion: '^9.1.1' | ||
}, | ||
{ | ||
author: '', | ||
author: "John-David Dalton <john.david.dalton@gmail.com>", | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'got', | ||
name: 'lodash', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/sindresorhus/got.git', | ||
link: 'git+https://github.com/lodash/lodash.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
installedVersion: '4.17.21', | ||
definedVersion: '^4.17.20' | ||
}, | ||
{ | ||
author: 'Dominic Tarr dominic.tarr@gmail.com dominictarr.com', | ||
author: 'GitHub Inc.', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'rc', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: '(BSD-2-Clause OR MIT OR Apache-2.0)', | ||
link: 'git+https://github.com/dominictarr/rc.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: '', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'semver', | ||
@@ -176,109 +211,65 @@ licensePeriod: 'perpetual', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
installedVersion: '7.3.7', | ||
definedVersion: '^7.3.5' | ||
}, | ||
] | ||
// raw data we use to generate the expected results for default fields test | ||
const EXPECTED_LOCAL_PACKAGES_RAW_DATA = [ | ||
{ | ||
author: 'James Halliday mail@substack.net http://substack.net', | ||
author: 'Caolan McMahon', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'text-table', | ||
name: 'async', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git://github.com/substack/text-table.git', | ||
link: 'n/a', | ||
installedFrom: "github:caolan/async", | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
installedVersion: '3.2.4', | ||
definedVersion: 'n/a' | ||
}, | ||
{ | ||
author: 'Yaniv Kessler', | ||
author: 'GitHub Inc.', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'visit-values', | ||
name: 'semver', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'https://github.com/kessler/node-visit-values', | ||
licenseType: 'ISC', | ||
link: 'git+https://github.com/npm/node-semver.git', | ||
installedFrom: "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
installedVersion: '7.3.6', | ||
definedVersion: '^7.3.0' | ||
}, | ||
{ | ||
author: 'Mario Nebl hello@herebecode.com', | ||
author: 'Josh Junon <josh.junon@protonmail.com>', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: '@commitlint/cli', | ||
name: 'debug', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/conventional-changelog/commitlint.git', | ||
link: 'n/a', | ||
installedFrom: "git://github.com/debug-js/debug.git", | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
installedVersion: '4.3.4', | ||
definedVersion: 'n/a' | ||
}, | ||
{ | ||
author: 'Mario Nebl hello@herebecode.com', | ||
author: 'John Doe', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: '@commitlint/config-conventional', | ||
name: 'my-local-package', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/conventional-changelog/commitlint.git', | ||
link: 'n/a', | ||
installedFrom: "file:local-libs/my-local-package", | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: 'Typicode typicode@gmail.com', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'husky', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/typicode/husky.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: 'TJ Holowaychuk tj@vision-media.ca', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'mocha', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/mochajs/mocha.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: 'Pedro Teixeira pedro.teixeira@gmail.com', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'nock', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'MIT', | ||
link: 'git+https://github.com/nock/nock.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
}, | ||
{ | ||
author: 'Ben Coe ben@npmjs.com', | ||
department: 'kessler', | ||
relatedTo: 'stuff', | ||
name: 'standard-version', | ||
licensePeriod: 'perpetual', | ||
material: 'material', | ||
licenseType: 'ISC', | ||
link: 'git+https://github.com/conventional-changelog/standard-version.git', | ||
remoteVersion: '_VERSION_', | ||
installedVersion: '_VERSION_', | ||
definedVersion: '_VERSION_' | ||
} | ||
installedVersion: '1.1.4', | ||
definedVersion: 'n/a' | ||
}, | ||
] | ||
@@ -293,15 +284,5 @@ | ||
{{department}},{{relatedTo}},[[@kessler/tableify]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[debug]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[eol]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[got]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[rc]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[mocha]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[lodash]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[semver]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[text-table]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[visit-values]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[@commitlint/cli]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[@commitlint/config-conventional]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[husky]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[mocha]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[nock]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
{{department}},{{relatedTo}},[[standard-version]],{{licensePeriod}},{{material}},{{licenseType}},{{link}},{{remoteVersion}},{{installedVersion}},{{definedVersion}},{{author}} | ||
` | ||
@@ -317,15 +298,5 @@ | ||
{{department}} {{relatedTo}} [[@kessler/tableify]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[debug]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[eol]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[got]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[rc]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[mocha]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[lodash]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[semver]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[text-table]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[visit-values]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[@commitlint/cli]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[@commitlint/config-conventional]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[husky]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[mocha]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[nock]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
{{department}} {{relatedTo}} [[standard-version]] {{licensePeriod}} {{material}} {{licenseType}} {{link}} {{remoteVersion}} {{installedVersion}} {{definedVersion}} {{author}} | ||
` |
@@ -1,7 +0,6 @@ | ||
const assert = require('assert') | ||
const extractLicense = require('../lib/extractLicense.js') | ||
import assert from 'node:assert'; | ||
import extractLicense from '../lib/extractLicense.js'; | ||
describe('extractLicense', function () { | ||
it('if its a string', function () { | ||
describe('extractLicense', function() { | ||
it('if it is a string', function() { | ||
const license = extractLicense({ license: '123' }) | ||
@@ -11,11 +10,16 @@ assert.strictEqual(license, '123') | ||
it('if its an array', function () { | ||
it('if it is an array', function() { | ||
const license = extractLicense({ licenses: [{ type: '123' }, { type: '456' }] }) | ||
assert.strictEqual(license, '123, 456') | ||
}) | ||
it('cannot extract for some reason', function () { | ||
it('if it is an empty array', function() { | ||
const license = extractLicense({ licenses: [] }) | ||
assert.strictEqual(license, 'n/a') | ||
}) | ||
it('cannot extract for some reason', function() { | ||
const license = extractLicense('lkasdlkjsdlkj') | ||
assert(!license) | ||
assert.strictEqual(license, 'n/a') | ||
}) | ||
}) |
@@ -1,6 +0,6 @@ | ||
const assert = require('assert') | ||
const extractLink = require('../lib/extractLink.js') | ||
import assert from 'node:assert'; | ||
import extractLink from '../lib/extractLink.js'; | ||
describe('extractLink', function () { | ||
it('extracts the repository link if its there', function () { | ||
describe('extractLink', function() { | ||
it('extracts the repository link if its there', function() { | ||
const link = extractLink({ repository: { url: 'http://lala.com' }}) | ||
@@ -10,3 +10,3 @@ assert.strictEqual(link, 'http://lala.com') | ||
it('search for another http link if repo link isnt there', function () { | ||
it('search for another http link if repo link is not there', function() { | ||
const link = extractLink({ url: 'http://lala.com' }) | ||
@@ -16,8 +16,3 @@ assert.strictEqual(link, 'http://lala.com') | ||
it('search for another http link if repo link isnt there', function () { | ||
const link = extractLink({ repo: 'git://lala.com' }) | ||
assert.strictEqual(link, 'git://lala.com') | ||
}) | ||
it('returns nothing otherwise', function () { | ||
it('returns nothing otherwise', function() { | ||
const link = extractLink({ url: 'lala.com' }) | ||
@@ -24,0 +19,0 @@ assert(!link) |
@@ -1,11 +0,11 @@ | ||
const got = require('got') | ||
const semver = require('semver') | ||
const debug = require('debug')('license-report:addRemoteVersion') | ||
const packageJson = require('../../package.json') | ||
const packageLockJson = require('../../package-lock.json') | ||
const config = require('../../lib/config.js') | ||
import got from 'got'; | ||
import semver from 'semver'; | ||
import createDebugMessages from 'debug'; | ||
import config from '../../lib/config.js'; | ||
const debug = createDebugMessages('license-report:expectedOutput'); | ||
/* | ||
get latest version from registry and add it to the entry in the expectedData; | ||
the field 'installedVersion' in the packagesData entries must contain the | ||
the field 'definedVersion' in the packagesData entries must contain the | ||
package name with the range character from the package.json to find the | ||
@@ -22,3 +22,4 @@ latest version satisfying the defined range (the range character will be | ||
const options = { | ||
retry: config.httpRetryOptions.maxAttempts, | ||
retry: config.httpRetryOptions, | ||
timeout: config.httpTimeoutOptions, | ||
hooks: { | ||
@@ -38,25 +39,26 @@ beforeRetry: [ | ||
} | ||
const packagesJson = await got(uri, options).json() | ||
let packagesJson = {} | ||
try { | ||
packagesJson = await got(uri, options).json() | ||
} catch (error) { | ||
packagesJson.error = `http request to npm for package "${dependency.name}" failed with error '${error}'` | ||
} | ||
// find the right version for this package | ||
const versions = Object.keys(packagesJson.versions) | ||
const version = semver.maxSatisfying(versions, dependency.definedVersion) | ||
if (version) { | ||
dependency.remoteVersion = version.toString() | ||
if(packagesJson.versions) { | ||
const versions = Object.keys(packagesJson.versions) | ||
const version = semver.maxSatisfying(versions, dependency.definedVersion) | ||
if (version) { | ||
dependency.remoteVersion = version.toString() | ||
} | ||
} | ||
} | ||
/* | ||
add current values for definedVersion, installedVersion and remoteVersion to list of expectedData | ||
*/ | ||
module.exports.addVersionToExpectedData = async (expectedData) => { | ||
// add version from package.json (dev-) dependencies as installedVersion | ||
const packagesList = Object.assign(Object.assign({}, packageJson.dependencies), packageJson.devDependencies) | ||
const packagesData = expectedData.map(packageData => { | ||
packageData.definedVersion = packagesList[packageData.name] | ||
packageData.installedVersion = packageLockJson.dependencies[[packageData.name]].version | ||
return packageData | ||
}) | ||
await Promise.all(packagesData.map(async (packageData) => { | ||
/** | ||
* Add remoteVersion to objects in array of expectedData | ||
* @param {[object]} expectedData - array with expected data containing placeholders for remote versions | ||
*/ | ||
async function addRemoteVersionsToExpectedData(expectedData) { | ||
await Promise.all(expectedData.map(async (packageData) => { | ||
await addRemoteVersion(packageData) | ||
@@ -69,3 +71,3 @@ })) | ||
*/ | ||
module.exports.rawDataToJson = (rawData) => { | ||
function rawDataToJson(rawData) { | ||
return rawData | ||
@@ -77,3 +79,3 @@ } | ||
*/ | ||
module.exports.rawDataToCsv = (expectedData, csvTemplate) => { | ||
function rawDataToCsv(expectedData, csvTemplate) { | ||
const fieldNames = ['author', 'department', 'relatedTo', 'licensePeriod', 'material', 'licenseType', 'link', 'remoteVersion', 'installedVersion', 'definedVersion'] | ||
@@ -106,3 +108,3 @@ const packageNamePattern = /\[\[(.+)]]/ | ||
*/ | ||
module.exports.rawDataToTable = (expectedData, tableTemplate) => { | ||
function rawDataToTable(expectedData, tableTemplate) { | ||
const columnDefinitions = { | ||
@@ -173,3 +175,3 @@ author: {title: 'author', maxColumnWidth: 0}, | ||
*/ | ||
module.exports.rawDataToHtml = (expectedData, htmlTemplate) => { | ||
function rawDataToHtml(expectedData, htmlTemplate) { | ||
const fieldNames = ['author', 'department', 'relatedTo', 'licensePeriod', 'material', 'licenseType', 'link', 'remoteVersion', 'installedVersion', 'definedVersion'] | ||
@@ -203,2 +205,10 @@ const packageNamePattern = /\[\[(.+)]]/ | ||
return updatedTemplate | ||
} | ||
} | ||
export default { | ||
addRemoteVersionsToExpectedData, | ||
rawDataToJson, | ||
rawDataToCsv, | ||
rawDataToTable, | ||
rawDataToHtml | ||
} |
@@ -1,8 +0,11 @@ | ||
const assert = require('assert') | ||
const path = require('path') | ||
const fs = require('fs') | ||
const eol = require('eol') | ||
const config = require('../lib/config.js') | ||
const getFormatter = require('../lib/getFormatter.js') | ||
import assert from 'node:assert'; | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import url from 'node:url'; | ||
import eol from 'eol'; | ||
import config from '../lib/config.js'; | ||
import getFormatter from '../lib/getFormatter.js'; | ||
const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); | ||
describe('formatter for json', () => { | ||
@@ -9,0 +12,0 @@ it('produces a report', () => { |
@@ -1,20 +0,231 @@ | ||
const assert = require('assert') | ||
const getPackageJson = require('../lib/getPackageJson.js') | ||
import assert from 'node:assert'; | ||
import nock from 'nock'; | ||
import config from '../lib/config.js'; | ||
import getPackageDataFromRepository from '../lib/getPackageDataFromRepository.js'; | ||
describe('getPackageJson', () => { | ||
/** | ||
* Fetching data from the (private) repository gets mocked to get independent from | ||
* varying data on the server and from having a real private repository. | ||
*/ | ||
describe('getPackageDataFromRepository', function() { | ||
this.timeout(20000) | ||
let originalHttpRetryLimit | ||
beforeEach(function() { | ||
originalHttpRetryLimit = config.httpRetryOptions.limit | ||
}) | ||
afterEach(function() { | ||
config.httpRetryOptions.limit = originalHttpRetryLimit | ||
nock.cleanAll() | ||
}) | ||
it('gets the information about the package "semver" from server', async () => { | ||
const packageJson = await getPackageJson('semver') | ||
assert.strictEqual(packageJson.homepage, 'https://github.com/npm/node-semver#readme') | ||
const packageName = 'semver' | ||
// Mock the npm private repository response | ||
config.httpRetryOptions.limit = 1 | ||
const scope = nock(config.registry, {"encodedQueryParams":true}) | ||
.get(`/${packageName}`) | ||
.reply(200, responses.semver) | ||
const packageJson = await getPackageDataFromRepository('semver') | ||
assert.strictEqual(packageJson.name, packageName) | ||
assert.ok(packageJson.versions.hasOwnProperty('7.3.7')) | ||
assert.ok(packageJson.versions['7.3.7'].hasOwnProperty('dist')) | ||
assert.ok(packageJson.versions['7.3.7']['dist'].hasOwnProperty('tarball')) | ||
assert.ok(packageJson.versions['7.3.7'].hasOwnProperty('repository')) | ||
assert.ok(packageJson.versions['7.3.7']['repository'].hasOwnProperty('url')) | ||
assert.ok(scope.isDone()) | ||
}) | ||
it('throws on getting information about non existing package', async () => { | ||
await assert.rejects( | ||
getPackageJson('packagedoesnotexist'), | ||
(err) => { | ||
assert.strictEqual(err.name, 'HTTPError') | ||
assert.strictEqual(err.message, 'Response code 404 (Not Found)') | ||
return true | ||
} | ||
) | ||
it('gets empty object for non existing package', async () => { | ||
const packageJson = await getPackageDataFromRepository('packagedoesnotexist') | ||
assert.deepEqual(packageJson, {}) | ||
}) | ||
}) | ||
}) | ||
describe('getPackageDataFromRepository with private repository', function() { | ||
this.timeout(20000) | ||
let originalConfigRegistry | ||
let originalConfigNpmTokenEnvVar | ||
let originalHttpRetryLimit | ||
beforeEach(function() { | ||
originalConfigRegistry = config.registry | ||
originalConfigNpmTokenEnvVar = config.npmTokenEnvVar | ||
originalHttpRetryLimit = config.httpRetryOptions.limit | ||
}) | ||
afterEach(function() { | ||
config.registry = originalConfigRegistry | ||
config.npmTokenEnvVar = originalConfigNpmTokenEnvVar | ||
config.httpRetryOptions.limit = originalHttpRetryLimit | ||
nock.cleanAll() | ||
}) | ||
it('gets npm token via environment variable given in config file', function() { | ||
const envVarName = 'TEST_NPM_TOKEN_LR' | ||
const testToken = Math.random().toString(36).substring(2) | ||
config.npmTokenEnvVar = envVarName | ||
process.env[envVarName] = testToken | ||
const npmTokenFromConfig = process.env[config.npmTokenEnvVar] || '' | ||
assert.strictEqual(npmTokenFromConfig, testToken) | ||
}) | ||
it('gets data from repository without authorization', async () => { | ||
const packageName = 'async' | ||
// Mock the config for accessing a npm private repository | ||
const npmRegistryHost = 'my.private.registry.com' | ||
const npmRegistry = `https://${npmRegistryHost}/` | ||
config.registry = npmRegistry | ||
process.env['NPM_TOKEN'] = '' | ||
config.httpRetryOptions.limit = 1 | ||
// Mock the npm private repository response | ||
const scope = nock(npmRegistry, {"encodedQueryParams":true}) | ||
.get(`/${packageName}`) | ||
.reply(200, responses.async) | ||
const packageReportData = await getPackageDataFromRepository(packageName) | ||
assert.strictEqual(packageReportData.name, packageName) | ||
assert.ok(packageReportData.versions.hasOwnProperty('3.2.0')) | ||
assert.ok(packageReportData.versions['3.2.0'].hasOwnProperty('dist')) | ||
assert.ok(packageReportData.versions['3.2.0']['dist'].hasOwnProperty('tarball')) | ||
assert.ok(packageReportData.versions['3.2.0'].hasOwnProperty('repository')) | ||
assert.ok(packageReportData.versions['3.2.0']['repository'].hasOwnProperty('url')) | ||
assert.ok(scope.isDone()) | ||
}) | ||
it('gets data from repository with authorization', async () => { | ||
const packageName = 'async' | ||
// Mock the config for accessing a npm private repository | ||
const npmRegistryHost = 'my.private.registry.com' | ||
const npmRegistry = `https://${npmRegistryHost}/` | ||
const npmToken = 'pp6j6gzcge' | ||
config.registry = npmRegistry | ||
process.env['NPM_TOKEN'] = npmToken | ||
config.httpRetryOptions.limit = 1 | ||
// Mock the npm private repository response | ||
const scope = nock(npmRegistry, {"encodedQueryParams":true}) | ||
.matchHeader("host", npmRegistryHost) | ||
.matchHeader("authorization", `Bearer ${npmToken}`) | ||
.get(`/${packageName}`) | ||
.reply(200, responses.async) | ||
const packageReportData = await getPackageDataFromRepository('async') | ||
assert.strictEqual(packageReportData.name, packageName) | ||
assert.ok(packageReportData.versions.hasOwnProperty('3.2.0')) | ||
assert.ok(packageReportData.versions['3.2.0'].hasOwnProperty('dist')) | ||
assert.ok(packageReportData.versions['3.2.0']['dist'].hasOwnProperty('tarball')) | ||
assert.ok(packageReportData.versions['3.2.0'].hasOwnProperty('repository')) | ||
assert.ok(packageReportData.versions['3.2.0']['repository'].hasOwnProperty('url')) | ||
assert.ok(scope.isDone()) | ||
}) | ||
it('throws error when using incorrect authorization', async () => { | ||
const packageName = 'async' | ||
// Mock the config for accessing a npm private repository | ||
const npmRegistryHost = 'my.private.registry.com' | ||
const npmRegistry = `https://${npmRegistryHost}/` | ||
const npmToken = 'pp6j6gzcge' | ||
config.registry = npmRegistry | ||
process.env['NPM_TOKEN'] = npmToken | ||
config.httpRetryOptions.limit = 1 | ||
// Mock the npm private repository response | ||
const scope = nock(npmRegistry, {"encodedQueryParams":true}) | ||
.matchHeader("host", npmRegistryHost) | ||
.matchHeader("authorization", `Bearer ${npmToken}`) | ||
.get(`/${packageName}`) | ||
.reply(401, {}) | ||
try { | ||
await getPackageDataFromRepository('async') | ||
} catch (error) { | ||
assert.strictEqual(error.name, 'HTTPError') | ||
assert.strictEqual(error.message, 'Response code 401 (Unauthorized)') | ||
} finally { | ||
assert.ok(scope.isDone()) | ||
} | ||
}) | ||
}) | ||
const responses = { | ||
async: { | ||
name: "async", | ||
description: "Higher-order functions and common patterns for asynchronous code", | ||
versions: { | ||
"3.2.0": { | ||
name: "async", | ||
description: "Higher-order functions and common patterns for asynchronous code", | ||
version: "3.2.0", | ||
repository: { | ||
type: "git", | ||
url: "git+https://github.com/caolan/async.git", | ||
}, | ||
dist: { | ||
tarball: "https://registry.npmjs.org/async/-/async-3.2.0.tgz", | ||
}, | ||
}, | ||
"3.2.1": { | ||
name: "async", | ||
description: "Higher-order functions and common patterns for asynchronous code", | ||
version: "3.2.1", | ||
repository: { | ||
type: "git", | ||
url: "git+https://github.com/caolan/async.git", | ||
}, | ||
dist: { | ||
tarball: "https://registry.npmjs.org/async/-/async-3.2.1.tgz", | ||
}, | ||
}, | ||
}, | ||
}, | ||
semver: { | ||
name: "semver", | ||
description: "The semantic version parser used by npm.", | ||
versions: { | ||
"7.3.6": { | ||
name: "semver", | ||
version: "7.3.6", | ||
description: "The semantic version parser used by npm.", | ||
repository: { | ||
type: "git", | ||
url: "git+https://github.com/npm/node-semver.git", | ||
}, | ||
dist: { | ||
tarball: "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", | ||
fileCount: 51, | ||
unpackedSize: 87319, | ||
}, | ||
}, | ||
"7.3.7": { | ||
name: "semver", | ||
version: "7.3.7", | ||
description: "The semantic version parser used by npm.", | ||
repository: { | ||
type: "git", | ||
url: "git+https://github.com/npm/node-semver.git", | ||
}, | ||
dist: { | ||
tarball: "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", | ||
fileCount: 51, | ||
unpackedSize: 87418, | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
476478
49
2433
199
6
Yes
+ Added@sindresorhus/is@5.6.0(transitive)
+ Added@szmarczak/http-timer@5.0.1(transitive)
+ Addedcacheable-lookup@7.0.0(transitive)
+ Addedcacheable-request@10.2.14(transitive)
+ Addedform-data-encoder@2.1.4(transitive)
+ Addedget-stream@6.0.1(transitive)
+ Addedgot@12.6.1(transitive)
+ Addedhttp2-wrapper@2.2.1(transitive)
+ Addedlowercase-keys@3.0.0(transitive)
+ Addedmimic-response@4.0.0(transitive)
+ Addednormalize-url@8.0.1(transitive)
+ Addedp-cancelable@3.0.0(transitive)
+ Addedresponselike@3.0.0(transitive)
- Removed@sindresorhus/is@4.6.0(transitive)
- Removed@szmarczak/http-timer@4.0.6(transitive)
- Removed@types/cacheable-request@6.0.3(transitive)
- Removed@types/keyv@3.1.4(transitive)
- Removed@types/node@22.7.9(transitive)
- Removed@types/responselike@1.0.3(transitive)
- Removedcacheable-lookup@5.0.4(transitive)
- Removedcacheable-request@7.0.4(transitive)
- Removedclone-response@1.0.3(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removedget-stream@5.2.0(transitive)
- Removedgot@11.8.6(transitive)
- Removedhttp2-wrapper@1.0.3(transitive)
- Removedlowercase-keys@2.0.0(transitive)
- Removedmimic-response@1.0.1(transitive)
- Removednormalize-url@6.1.0(transitive)
- Removedonce@1.4.0(transitive)
- Removedp-cancelable@2.1.1(transitive)
- Removedpump@3.0.2(transitive)
- Removedresponselike@2.0.1(transitive)
- Removedundici-types@6.19.8(transitive)
- Removedwrappy@1.0.2(transitive)
Updateddebug@^4.3.4
Updatedgot@^12.1.0
Updatedsemver@^7.3.7