kessler / license-report

create a short report about a project's dependencies (license, url etc)
MIT License
223 stars 39 forks source link

Feat: Include License path in output #146

Closed mahyarmirrashed closed 11 months ago

mahyarmirrashed commented 11 months ago

It would be helpful to have in the output, a relative path to the actual LICENSE file given if the dependency is installed.

BePo65 commented 11 months ago

license-report just takes the entry 'licenseType' from the package.json file of the project. It is not guaranteed that a package has a license file. If you need that field, perhaps take a look at the license-downloader that gets all the license files.

mahyarmirrashed commented 11 months ago

Seems fair enough. However, license-downloader would be slow since it would make API calls and retrieve them on every build. It would be better for me to have something that looks directly into the node_packages directory to find each packages' LICENSE file after something like npm ci. That way, license retrieval and processing is done after required work anyway. Plus, there is no guarantee that all packages will be hosted on GitHub to use the GitHub method. Maybe a feature to match the first instance of LICENSE in each project's root would be a useful feature?

BePo65 commented 11 months ago

the field 'license' in a package.json file can be a string or an object.

If it is a string: where to look for a file and what would be the name of the file? (or is this the "match the first instance of LICENSE in each project's root" part of our last comment? But then this is IMHO no generic solution).

If it is an object, it may have an 'url' field or not - same problem as before. And in that case it is probably not a local file path.

And in what format the output field should be? We have linux and windows based systems. relative or absolute paths?

What about mono repos?

BePo65 commented 11 months ago

Perhaps yore requirement can be solved with a small node script (I called it addLicensePath.js) that gets the output from license-report and adds a field named licensePath (I assume you are using the json output format):

#!/usr/bin/env node

import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';

let inputString = '';

process.stdin.resume();

// make stdin return a string
process.stdin.setEncoding('utf-8');

process.stdin.on('data', inputStdin => {
  // license-report emits only 1 line
  inputString += inputStdin;
});

process.stdin.on('end', () => {
    inputString = inputString.trim();
    main();
});

function getLicensePath(packageName, projectRootPath) {
  let licensePath = '';
  const elementPackagePath = path.join(projectRootPath, 'node_modules', packageName);
  if (fs.existsSync(elementPackagePath)) {
    ['LICENSE', 'LICENSE.md'].every(licenseFileName => {
      let elementLicensePath = path.join(elementPackagePath, licenseFileName);
      if (fs.existsSync(elementLicensePath)) {
        licensePath = path.relative(projectRootPath, elementLicensePath);
        return false;
      }
    });
  }

  return licensePath;
}

function main() {
  const projectRootPath = process.cwd();
  const licenseReport = JSON.parse(inputString);
  licenseReport.forEach(licenseEntry => {
    licenseEntry['licensePath'] = getLicensePath(licenseEntry.name, projectRootPath);
  });

  console.log(JSON.stringify(licenseReport));
}

And calling it with a script in package.json would look like that:

:
  "scripts": {
    "demo": "npx --yes license-report --fields=name --fields=installedVersion --fields=licenseType | node addLicensePath.js"
  },
  "type": "module",
: