Browse Source

initial commit

master
Feross Aboukhadijeh 7 years ago
commit
870d1e501a
  1. 10
      README.md
  2. 142
      cmd.js
  3. 54
      index.js
  4. 51
      package.json

10
README.md

@ -0,0 +1,10 @@
# thanks
### 🙌 Give thanks to the open source maintainers you depend on! ✨
## usage
```js
npx thanks
```

142
cmd.js

@ -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
}

54
index.js

@ -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 }

51
package.json

@ -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…
Cancel
Save