Skip to content

Instantly share code, notes, and snippets.

@tjklemz
Last active November 9, 2018 22:48
Show Gist options
  • Save tjklemz/0a21f450d8de8470f78cfe05d124fc75 to your computer and use it in GitHub Desktop.
Save tjklemz/0a21f450d8de8470f78cfe05d124fc75 to your computer and use it in GitHub Desktop.
Lists licenses of all direct dependencies in a monorepo (assumes packages folder). Will parse any License file if there is one and gives short format. Useful for About dialogs.
var fs = require('fs')
var path = require('path')
var cwd = typeof __dirname === 'undefined' ? process.cwd() : __dirname
var repos = fs.readdirSync('./packages').map(path => cwd+'/packages/'+path).filter(path => fs.lstatSync(path).isDirectory()).concat([cwd])
var getParent = (p, n = 1) => p.split(path.sep).slice(0, -n).join(path.sep)
var allDeps = repos
.map(repo => repo+'/package.json')
.filter(p => fs.existsSync(p))
.map(package => Object.keys(require(package).dependencies).map(dep => {
delete require.cache[dep]
var p = path.dirname(require.resolve(dep, { paths: repos }))
var license
var dirs = [p, getParent(p, 1), getParent(p, 2)]
var files = ['package.json', 'LICENSE', 'LICENSE.txt', 'LICENSE.md', 'LICENCE', 'LICENCE.txt', 'LICENCE.md']
for (let dir of dirs) {
for (let file of files) {
let f = path.join(dir, file)
if (fs.existsSync(f)) {
if (file === 'package.json') {
let l = require(f).license
// TODO: parse the "SEE LICENSE IN <FILENAME>", and also manually check for filenames
// (like it currently does), since many repos don't list a license or they incorrectly list it
if (l && !l.startsWith('SEE ')) {
license = l
break
}
} else {
let lines = fs.readFileSync(f).toString().split('\n').map(line => line.trim()).filter(Boolean)
let l = lines.find(line => line.toLowerCase().match(/(licence|license)/)) || lines[0]
if (l) {
license = l
break
}
}
}
}
if (license) {
break
}
}
return {
[dep]: license || 'UNKNOWN'
}
}))
.reduce((allDeps, deps) => allDeps.concat(deps), [])
.reduce((allDeps, dep) => ({ ...allDeps, ...dep }))
console.log(Object.keys(allDeps).map(dep => dep + '\t' + allDeps[dep]).join('\n'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment