mirror of https://github.com/lukechilds/thanks.git
Feross Aboukhadijeh
7 years ago
commit
870d1e501a
4 changed files with 257 additions and 0 deletions
@ -0,0 +1,10 @@ |
|||
# thanks |
|||
|
|||
### 🙌 Give thanks to the open source maintainers you depend on! ✨ |
|||
|
|||
## usage |
|||
|
|||
```js |
|||
npx thanks |
|||
``` |
|||
|
@ -0,0 +1,142 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
const chalk = require('chalk') |
|||
const minimist = require('minimist') |
|||
const pify = require('pify') |
|||
const pkgDir = require('pkg-dir') |
|||
const readPackageTree = require('read-package-tree') |
|||
const RegistryClient = require('npm-registry-client') // TODO: use npm-registry-fetch
|
|||
const registryUrl = require('registry-url') |
|||
const stripAnsi = require('strip-ansi') |
|||
const textTable = require('text-table') |
|||
|
|||
const donees = require('./') |
|||
|
|||
const readPackageTreeAsync = pify(readPackageTree) |
|||
|
|||
init().catch(handleError) |
|||
|
|||
async function init () { |
|||
const argv = minimist(process.argv.slice(2)) |
|||
|
|||
const cwd = argv._[0] || process.cwd() |
|||
|
|||
const authors = {} |
|||
const client = createRegistryClient() |
|||
|
|||
// Get all packages in the nearest `node_modules` folder
|
|||
const rootPath = await pkgDir(cwd) |
|||
const packageTree = await readPackageTreeAsync(rootPath) |
|||
const pkgNames = packageTree.children.map(node => node.package.name) |
|||
|
|||
// Get latest registry data on each local package, since the local data does
|
|||
// not include the list of maintainers
|
|||
const pkgs = await Promise.all(pkgNames.map(fetchPkg)) |
|||
|
|||
pkgs.forEach(pkg => { |
|||
pkg.maintainers |
|||
.map(maintainer => maintainer.name) |
|||
.forEach(author => addPackageAuthor(pkg.name, author)) |
|||
}) |
|||
|
|||
const rows = Object.keys(authors) |
|||
.filter(author => donees.authors[author] != null) |
|||
.sort((author1, author2) => authors[author2].length - authors[author1].length) |
|||
.map(author => { |
|||
const deps = authors[author] |
|||
return [ |
|||
chalk.green(author), |
|||
donees.authors[author], |
|||
`${deps.length} packages including ${deps.slice(0, 3).join(', ')}` |
|||
] |
|||
}) |
|||
|
|||
rows.unshift([ |
|||
chalk.underline('Author'), |
|||
chalk.underline('Where to Donate'), |
|||
chalk.underline('Dependencies') |
|||
]) |
|||
|
|||
const tableOpts = { |
|||
// align: ['l', 'l', 'l'],
|
|||
stringLength: str => stripAnsi(str).length |
|||
} |
|||
|
|||
const table = textTable(rows, tableOpts) |
|||
console.log(table) |
|||
|
|||
function createRegistryClient () { |
|||
const opts = { |
|||
log: { |
|||
error () {}, |
|||
http () {}, |
|||
info () {}, |
|||
silly () {}, |
|||
verbose () {}, |
|||
warn () {} |
|||
} |
|||
} |
|||
const client = new RegistryClient(opts) |
|||
client.getAsync = pify(client.get.bind(client)) |
|||
return client |
|||
} |
|||
|
|||
async function fetchPkg (pkgName) { |
|||
// The registry does not support fetching versions for scoped packages
|
|||
const isScopedPackage = pkgName.includes('/') |
|||
const url = isScopedPackage |
|||
? `${registryUrl()}${pkgName.replace('/', '%2F')}` |
|||
: `${registryUrl()}${pkgName}/latest` |
|||
|
|||
const opts = { |
|||
timeout: 30 * 1000, |
|||
staleOk: true |
|||
} |
|||
return client.getAsync(url, opts) |
|||
} |
|||
|
|||
function addPackageAuthor (pkgName, author) { |
|||
if (authors[author] == null) authors[author] = [] |
|||
authors[author].push(pkgName) |
|||
} |
|||
|
|||
// const rootPkg = await fetchLocalPkg()
|
|||
|
|||
// const rootDeps = [].concat(
|
|||
// findDeps(rootPkg, 'dependencies'),
|
|||
// findDeps(rootPkg, 'devDependencies'),
|
|||
// findDeps(rootPkg, 'optionalDependencies')
|
|||
// )
|
|||
|
|||
// const queue = [].push(...rootDeps)
|
|||
|
|||
// while (queue.length > 0) {
|
|||
// const pkgs = await Promise.all(queue.slice(0, CONCURRENCY).map(fetchPkg))
|
|||
// }
|
|||
} |
|||
|
|||
// async function fetchLocalPkg () {
|
|||
// const pkgPath = await pkgUp()
|
|||
// const pkgStr = await readFileAsync(pkgPath, 'utf8')
|
|||
|
|||
// try {
|
|||
// const pkg = JSON.parse(pkgStr)
|
|||
// normalizePackage(pkg)
|
|||
// return pkg
|
|||
// } catch (err) {
|
|||
// err.message = `Failed to parse package.json: ${err.message}`
|
|||
// throw err
|
|||
// }
|
|||
// }
|
|||
|
|||
// function findDeps (pkg, type) {
|
|||
// return pkg[type] && typeof pkg[type] === 'object'
|
|||
// ? Object.keys(pkg[type])
|
|||
// : []
|
|||
// }
|
|||
|
|||
function handleError (err) { |
|||
console.error(`thanks: Error: ${err.message}`) |
|||
console.error(err.stack) |
|||
process.exitCode = 1 |
|||
} |
@ -0,0 +1,54 @@ |
|||
/* |
|||
* npm username -> donate page |
|||
* |
|||
* Whenever a `thanks` user has a package owned by one of these authors in their |
|||
* package tree, they will be prompted to donate. |
|||
*/ |
|||
const authors = { |
|||
andrewnez: 'https://en.liberapay.com/andrew/', |
|||
bevacqua: 'https://www.patreon.com/bevacqua', |
|||
feross: 'https://www.patreon.com/feross', |
|||
getify: 'https://www.patreon.com/getify', |
|||
hueniverse: 'https://www.patreon.com/eranhammer', |
|||
mafintosh: 'https://www.patreon.com/mafintosh', |
|||
mikeal: 'https://www.patreon.com/mikeal', |
|||
mmckegg: 'https://www.patreon.com/MattMcKegg', |
|||
mpj: 'https://www.patreon.com/funfunfunction', |
|||
noffle: 'https://en.liberapay.com/noffle/', |
|||
paulirish: 'https://en.liberapay.com/paulirish/', |
|||
sindresorhus: 'https://www.patreon.com/sindresorhus', |
|||
staltz: 'https://en.liberapay.com/andrestaltz/', |
|||
thlorenz: 'https://www.patreon.com/thlorenz', |
|||
yyx990803: 'https://www.patreon.com/evanyou' |
|||
} |
|||
|
|||
/* |
|||
* npm package name -> donate page |
|||
* |
|||
* Whenever a `thanks` user has one these exact packages in their package tree, |
|||
* they will be prompted to donate. |
|||
*/ |
|||
const packages = { |
|||
'babel-core': 'https://opencollective.com/babel', |
|||
bower: 'https://opencollective.com/bower', |
|||
cheerio: 'https://opencollective.com/cheerio', |
|||
choo: 'https://opencollective.com/choo', |
|||
gulp: 'https://opencollective.com/gulpjs', |
|||
'gulp-cli': 'https://opencollective.com/gulpjs', |
|||
hoodie: 'https://opencollective.com/hoodie', |
|||
koa: 'https://opencollective.com/koajs', |
|||
'material-ui': 'https://opencollective.com/material-ui', |
|||
mocha: 'https://opencollective.com/mochajs', |
|||
parcel: 'https://opencollective.com/parcel', |
|||
preact: 'https://opencollective.com/preact', |
|||
pug: 'https://opencollective.com/pug', |
|||
'react-native-elements': 'https://opencollective.com/react-native-elements', |
|||
'redux-devtools-extension': 'https://opencollective.com/redux-devtools-extension', |
|||
rollup: 'https://opencollective.com/rollup', |
|||
'socket.io': 'https://opencollective.com/socketio', |
|||
tachyons: 'https://opencollective.com/tachyons', |
|||
webpack: 'https://opencollective.com/webpack', |
|||
yo: 'https://opencollective.com/yeoman' |
|||
} |
|||
|
|||
module.exports = { authors, packages } |
@ -0,0 +1,51 @@ |
|||
{ |
|||
"name": "thanks", |
|||
"description": "Give thanks to the open source maintainers you depend on!", |
|||
"version": "0.0.0", |
|||
"author": { |
|||
"name": "Feross Aboukhadijeh", |
|||
"email": "feross@feross.org", |
|||
"url": "https://feross.org" |
|||
}, |
|||
"bin": "cmd.js", |
|||
"bugs": { |
|||
"url": "https://github.com/feross/thanks/issues" |
|||
}, |
|||
"dependencies": { |
|||
"chalk": "^2.3.0", |
|||
"minimist": "^1.2.0", |
|||
"npm-registry-client": "^8.5.0", |
|||
"pify": "^3.0.0", |
|||
"pkg-dir": "^2.0.0", |
|||
"read-package-tree": "^5.1.6", |
|||
"registry-url": "^3.1.0", |
|||
"strip-ansi": "^4.0.0", |
|||
"text-table": "^0.2.0" |
|||
}, |
|||
"devDependencies": { |
|||
"standard": "*" |
|||
}, |
|||
"keywords": [ |
|||
"thanks", |
|||
"open source", |
|||
"sustainability", |
|||
"donate", |
|||
"support", |
|||
"funding", |
|||
"patreon", |
|||
"donor", |
|||
"thank you", |
|||
"fund", |
|||
"sustain", |
|||
"earn" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git://github.com/feross/thanks.git" |
|||
}, |
|||
"scripts": { |
|||
"test": "standard" |
|||
} |
|||
} |
Loading…
Reference in new issue