├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── bin └── top-npm-users.js ├── index.js ├── package.json ├── test ├── fixtures │ ├── bejesus-cli.json │ └── fake-changes-stream.js └── npm-user-download-counts.js └── top-npm-users.md.mustache /.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output 2 | node_modules 3 | .DS_Store 4 | output 5 | build 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Contributors 2 | 3 | Permission to use, copy, modify, and/or distribute this software 4 | for any purpose with or without fee is hereby granted, provided 5 | that the above copyright notice and this permission notice 6 | appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE 11 | LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 12 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 13 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 14 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # top-npm-users ([git.io/npm-top](http://git.io/npm-top)) 2 | 3 | [![Build Status](https://travis-ci.org/bcoe/top-npm-users.svg)](https://travis-ci.org/bcoe/top-npm-users) 4 | [![Coverage Status](https://coveralls.io/repos/bcoe/top-npm-users/badge.svg?branch=master)](https://coveralls.io/r/bcoe/top-npm-users?branch=master) 5 | [![NPM version](https://img.shields.io/npm/v/top-npm-users.svg)](https://www.npmjs.com/top-npm-users) 6 | 7 | npm users sorted by the monthly downloads of their modules. 8 | 9 | Inspired by [top-github-users](https://github.com/paulmillr/top-github-users) 10 | 11 | ## Installing 12 | 13 | ``` 14 | npm i top-npm-users -g 15 | ``` 16 | 17 | ## Usage 18 | 19 | Generate the statistics: 20 | 21 | ```sh 22 | top-npm-users calculate 23 | ``` 24 | 25 | Generate the Markdown: 26 | 27 | ```sh 28 | top-npm-users render 29 | ``` 30 | 31 | ## How Counts Are Calculated 32 | 33 | top-npm-users walks a stream of the npm registry using [changes-stream](https://www.npmjs.com/package/changes-stream) and pulls down statistics 34 | from the [npm download counts api](https://github.com/npm/download-counts). 35 | 36 | ## License 37 | 38 | ISC 39 | -------------------------------------------------------------------------------- /bin/top-npm-users.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var TopUsers = require('../') 4 | 5 | require('yargs') 6 | .usage('$0 [command]') 7 | .command('calculate', 'walk the registry changes feed and calculate user download counts', function (yargs, argv) { 8 | var dc = new TopUsers() 9 | dc.calculate() 10 | }) 11 | .command('render', 'read in top-npm-users.json and render the markdown report', function (yargs, argv) { 12 | var dc = new TopUsers() 13 | dc.render() 14 | }) 15 | .help('h') 16 | .alias('h', 'help') 17 | .demand(1, 'a command must be provided') 18 | .parse() 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash') 2 | var fs = require('fs') 3 | var handlebars = require('handlebars') 4 | var mkdirp = require('mkdirp') 5 | var moment = require('moment') 6 | var path = require('path') 7 | var queue = require('async').queue 8 | var request = require('request') 9 | 10 | function TopUsers (opts) { 11 | _.extend(this, { 12 | saveInterval: 15000, 13 | dirty: false, 14 | countsUrl: 'https://api.npmjs.org/downloads/point/last-month/', 15 | outputDirectory: './output/', 16 | jsonData: 'top-npm-users.json', 17 | templateName: 'top-npm-users.md', 18 | registryDb: 'https://replicate.npmjs.com/registry', 19 | downloadCounts: {}, 20 | ChangesStream: require('changes-stream') 21 | }, opts) 22 | } 23 | 24 | let backoff = 5000 25 | const backoffIncrement = 5000 26 | const queueConcurrency = 4 27 | 28 | TopUsers.prototype.calculate = function () { 29 | this._q = queue((task, callback) => { 30 | request.get({ 31 | json: true, 32 | url: this.countsUrl + encodeURIComponent(task.name) 33 | }, (err, res, obj) => { 34 | if (res && [200, 404].indexOf(res.statusCode) === -1) { 35 | err = Error('unexpected status = ' + res.statusCode) 36 | } 37 | if (err) { 38 | console.warn(err.message) 39 | setTimeout(() => { 40 | console.info(`retrying task ${task.name} backoff now ${backoff}`) 41 | task.failures++ 42 | if (task.failures < 3) this._q.push(task) 43 | return callback() 44 | }, backoff) 45 | backoff += backoffIncrement 46 | } else { 47 | backoff = backoffIncrement 48 | this.dirty = true 49 | this._updateUserCounts(task, obj.downloads) 50 | return callback() 51 | } 52 | }) 53 | }, queueConcurrency) 54 | 55 | var changes = new this.ChangesStream({ 56 | include_docs: true, 57 | db: this.registryDb 58 | }) 59 | 60 | changes.on('readable', () => { 61 | var change = changes.read() 62 | 63 | if (change.seq % 100 === 0) console.log('sequence #' + change.seq) 64 | 65 | if (change.doc && change.doc.maintainers) { 66 | this._q.push({ 67 | maintainers: change.doc.maintainers, 68 | name: change.doc.name, 69 | failures: 0 70 | }, (err) => { 71 | if (err) console.log(err.message) 72 | }) 73 | } 74 | }) 75 | 76 | this._saveInterval = setInterval(() => { 77 | if (this.dirty) { 78 | console.log('saving download counts (q = ' + this._q.length() + ')') 79 | mkdirp.sync(this.outputDirectory) 80 | fs.writeFileSync(this.outputDirectory + this.jsonData, JSON.stringify(this.downloadCounts, null, 2), 'utf-8') 81 | } 82 | }, this.saveInterval) 83 | } 84 | 85 | TopUsers.prototype._updateUserCounts = function (task, downloads) { 86 | task.maintainers.forEach((maintainer) => { 87 | if (!this.downloadCounts[maintainer.name]) this.downloadCounts[maintainer.name] = 0 88 | this.downloadCounts[maintainer.name] += downloads || 0 89 | }) 90 | } 91 | 92 | TopUsers.prototype.render = function () { 93 | var template = handlebars.compile( 94 | fs.readFileSync(path.resolve(__dirname, this.templateName + '.mustache'), 'utf-8') 95 | ) 96 | 97 | var result = template({ 98 | end: moment().format('ll'), 99 | start: moment().subtract(1, 'month').format('ll'), 100 | users: this._top100Users().map((u, i) => { 101 | return { 102 | name: u.name, 103 | downloads: u.downloads.toLocaleString(), 104 | index: i + 1 105 | } 106 | }) 107 | }) 108 | 109 | mkdirp.sync(this.outputDirectory) 110 | fs.writeFileSync(this.outputDirectory + this.templateName, result, 'utf-8') 111 | } 112 | 113 | TopUsers.prototype._top100Users = function () { 114 | var userMap = JSON.parse(fs.readFileSync(this.outputDirectory + this.jsonData, 'utf-8')) 115 | var users = [] 116 | 117 | Object.keys(userMap).forEach((k) => { 118 | users.push({ 119 | name: k, 120 | downloads: userMap[k] 121 | }) 122 | }) 123 | 124 | users.sort((a, b) => { 125 | return b.downloads - a.downloads 126 | }) 127 | 128 | return users.slice(0, 100) 129 | } 130 | 131 | TopUsers.prototype.stop = function () { 132 | if (this._saveInterval) clearInterval(this._saveInterval) 133 | } 134 | 135 | module.exports = TopUsers 136 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "top-npm-users", 3 | "version": "1.0.1", 4 | "description": "top npm users by download counts", 5 | "main": "index.js", 6 | "bin": "./bin/top-npm-users.js", 7 | "scripts": { 8 | "pretest": "standard", 9 | "test": "tap --coverage ./test/*.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+ssh://git@github.com/bcoe/top-npm-users.git" 14 | }, 15 | "keywords": [ 16 | "download", 17 | "stats", 18 | "counts" 19 | ], 20 | "author": "Ben Coe ", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/bcoe/top-npm-users/issues" 24 | }, 25 | "homepage": "https://github.com/bcoe/top-npm-users#readme", 26 | "devDependencies": { 27 | "chai": "^4.1.2", 28 | "nock": "^9.2.5", 29 | "rimraf": "^2.6.2", 30 | "standard": "^11.0.1", 31 | "tap": "^11.1.4" 32 | }, 33 | "dependencies": { 34 | "async": "^2.6.0", 35 | "changes-stream": "^2.2.0", 36 | "handlebars": "^4.0.11", 37 | "lodash": "^4.17.10", 38 | "mkdirp": "^0.5.1", 39 | "moment": "^2.22.1", 40 | "request": "^2.85.0", 41 | "yargs": "^11.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/fixtures/bejesus-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "seq": 79, 3 | "id": "bejesus-cli", 4 | "changes": [ 5 | { 6 | "rev": "1-9a15e641582b4894794943f1575767e0" 7 | } 8 | ], 9 | "doc": { 10 | "_id": "bejesus-cli", 11 | "_rev": "1-9a15e641582b4894794943f1575767e0", 12 | "name": "bejesus-cli", 13 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 14 | "dist-tags": { 15 | "latest": "0.2.4" 16 | }, 17 | "versions": { 18 | "0.0.1": { 19 | "name": "bejesus-cli", 20 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 21 | "version": "0.0.1", 22 | "homepage": "http://bejes.us/", 23 | "repository": "git://github.com/DanBUK/bejesus-api.git", 24 | "author": { 25 | "name": "Daniel Bartlett", 26 | "email": "dan@f-box.org", 27 | "url": "http://danb-uk.net/" 28 | }, 29 | "bin": { 30 | "bejesus": "bin/bejesus.js" 31 | }, 32 | "engines": { 33 | "node": "*" 34 | }, 35 | "dependencies": { 36 | "bejesus-api": "0.0.1" 37 | }, 38 | "_id": "bejesus-cli@0.0.1", 39 | "_engineSupported": true, 40 | "_npmVersion": "0.2.15", 41 | "_nodeVersion": "v0.2.6", 42 | "directories": { 43 | "bin": "./bin" 44 | }, 45 | "files": [ 46 | "" 47 | ], 48 | "_defaultsLoaded": true, 49 | "dist": { 50 | "shasum": "80193f6815adbe82122f53e479b5af9dfc900855", 51 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.0.1.tgz" 52 | } 53 | }, 54 | "0.0.2": { 55 | "name": "bejesus-cli", 56 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 57 | "version": "0.0.2", 58 | "homepage": "http://bejes.us/", 59 | "repository": "git://github.com/DanBUK/bejesus-api.git", 60 | "author": { 61 | "name": "Daniel Bartlett", 62 | "email": "dan@f-box.org", 63 | "url": "http://danb-uk.net/" 64 | }, 65 | "bin": { 66 | "bejesus": "bin/bejesus.js" 67 | }, 68 | "engines": { 69 | "node": "*" 70 | }, 71 | "dependencies": { 72 | "bejesus-api": "0.0.1" 73 | }, 74 | "_id": "bejesus-cli@0.0.2", 75 | "_engineSupported": true, 76 | "_npmVersion": "0.2.15", 77 | "_nodeVersion": "v0.2.6", 78 | "directories": { 79 | "bin": "./bin" 80 | }, 81 | "files": [ 82 | "" 83 | ], 84 | "_defaultsLoaded": true, 85 | "dist": { 86 | "shasum": "de66a9a18342c05a438f499069a917c5b42d29cf", 87 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.0.2.tgz" 88 | } 89 | }, 90 | "0.0.3": { 91 | "name": "bejesus-cli", 92 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 93 | "version": "0.0.3", 94 | "homepage": "http://bejes.us/", 95 | "repository": "git://github.com/DanBUK/bejesus-api.git", 96 | "author": { 97 | "name": "Daniel Bartlett", 98 | "email": "dan@f-box.org", 99 | "url": "http://danb-uk.net/" 100 | }, 101 | "bin": { 102 | "bejesus": "bin/bejesus.js" 103 | }, 104 | "engines": { 105 | "node": "*" 106 | }, 107 | "dependencies": { 108 | "bejesus-api": "0.0.3" 109 | }, 110 | "_id": "bejesus-cli@0.0.3", 111 | "_engineSupported": true, 112 | "_npmVersion": "0.2.15", 113 | "_nodeVersion": "v0.2.6", 114 | "directories": { 115 | "bin": "./bin" 116 | }, 117 | "files": [ 118 | "" 119 | ], 120 | "_defaultsLoaded": true, 121 | "dist": { 122 | "shasum": "594cc8f1b617d55a858af8de094ee8bb05de61d2", 123 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.0.3.tgz" 124 | } 125 | }, 126 | "0.1.0": { 127 | "name": "bejesus-cli", 128 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 129 | "version": "0.1.0", 130 | "homepage": "http://bejes.us/", 131 | "repository": "git://github.com/DanBUK/bejesus-api.git", 132 | "author": { 133 | "name": "Daniel Bartlett", 134 | "email": "dan@f-box.org", 135 | "url": "http://danb-uk.net/" 136 | }, 137 | "bin": { 138 | "bejesus": "bin/bejesus.js" 139 | }, 140 | "engines": { 141 | "node": "*" 142 | }, 143 | "dependencies": { 144 | "bejesus-api": "0.1.0" 145 | }, 146 | "_id": "bejesus-cli@0.1.0", 147 | "_engineSupported": true, 148 | "_npmVersion": "0.2.15", 149 | "_nodeVersion": "v0.2.5", 150 | "directories": { 151 | "bin": "./bin" 152 | }, 153 | "files": [ 154 | "" 155 | ], 156 | "_defaultsLoaded": true, 157 | "dist": { 158 | "shasum": "34fb8c71ba088234e94df3479f79278c7caecdbe", 159 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.0.tgz" 160 | } 161 | }, 162 | "0.1.1": { 163 | "name": "bejesus-cli", 164 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 165 | "version": "0.1.1", 166 | "homepage": "http://bejes.us/", 167 | "repository": "git://github.com/DanBUK/bejesus-api.git", 168 | "author": { 169 | "name": "Daniel Bartlett", 170 | "email": "dan@f-box.org", 171 | "url": "http://danb-uk.net/" 172 | }, 173 | "bin": { 174 | "bejesus": "bin/bejesus.js" 175 | }, 176 | "engines": { 177 | "node": "*" 178 | }, 179 | "dependencies": { 180 | "bejesus-api": "0.1.1" 181 | }, 182 | "_id": "bejesus-cli@0.1.1", 183 | "_engineSupported": true, 184 | "_npmVersion": "0.2.15", 185 | "_nodeVersion": "v0.2.5", 186 | "directories": { 187 | "bin": "./bin" 188 | }, 189 | "files": [ 190 | "" 191 | ], 192 | "_defaultsLoaded": true, 193 | "dist": { 194 | "shasum": "0b92065fab5dba4a40ea749d3a9c1d88469362bb", 195 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.1.tgz" 196 | } 197 | }, 198 | "0.1.2": { 199 | "name": "bejesus-cli", 200 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 201 | "version": "0.1.2", 202 | "homepage": "http://bejes.us/", 203 | "repository": "git://github.com/DanBUK/bejesus-api.git", 204 | "author": { 205 | "name": "Daniel Bartlett", 206 | "email": "dan@f-box.org", 207 | "url": "http://danb-uk.net/" 208 | }, 209 | "bin": { 210 | "bejesus": "bin/bejesus.js" 211 | }, 212 | "engines": { 213 | "node": "*" 214 | }, 215 | "dependencies": { 216 | "nodester-api": "0.1.0" 217 | }, 218 | "_id": "bejesus-cli@0.1.2", 219 | "_engineSupported": true, 220 | "_npmVersion": "0.2.15", 221 | "_nodeVersion": "v0.2.5", 222 | "directories": { 223 | "bin": "./bin" 224 | }, 225 | "files": [ 226 | "" 227 | ], 228 | "_defaultsLoaded": true, 229 | "dist": { 230 | "shasum": "b63a533877ce935bd54b47b4e05133d0fa90e485", 231 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.2.tgz" 232 | } 233 | }, 234 | "0.1.3": { 235 | "name": "bejesus-cli", 236 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 237 | "version": "0.1.3", 238 | "homepage": "http://bejes.us/", 239 | "repository": "git://github.com/DanBUK/bejesus-api.git", 240 | "author": { 241 | "name": "Daniel Bartlett", 242 | "email": "dan@f-box.org", 243 | "url": "http://danb-uk.net/" 244 | }, 245 | "bin": { 246 | "bejesus": "bin/bejesus.js" 247 | }, 248 | "engines": { 249 | "node": "*" 250 | }, 251 | "dependencies": { 252 | "nodester-api": "0.1.1" 253 | }, 254 | "_id": "bejesus-cli@0.1.3", 255 | "_engineSupported": true, 256 | "_npmVersion": "0.2.15", 257 | "_nodeVersion": "v0.2.5", 258 | "directories": { 259 | "bin": "./bin" 260 | }, 261 | "files": [ 262 | "" 263 | ], 264 | "_defaultsLoaded": true, 265 | "dist": { 266 | "shasum": "4e6e2f42722fd74e53e46e47db2d9ee57af3dfdf", 267 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.3.tgz" 268 | } 269 | }, 270 | "0.1.4": { 271 | "name": "bejesus-cli", 272 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 273 | "version": "0.1.4", 274 | "homepage": "http://bejes.us/", 275 | "repository": "git://github.com/DanBUK/bejesus-api.git", 276 | "author": { 277 | "name": "Daniel Bartlett", 278 | "email": "dan@f-box.org", 279 | "url": "http://danb-uk.net/" 280 | }, 281 | "bin": { 282 | "bejesus": "bin/bejesus.js" 283 | }, 284 | "engines": { 285 | "node": "*" 286 | }, 287 | "dependencies": { 288 | "nodester-api": "0.1.2" 289 | }, 290 | "_id": "bejesus-cli@0.1.4", 291 | "_engineSupported": true, 292 | "_npmVersion": "0.2.15", 293 | "_nodeVersion": "v0.2.5", 294 | "directories": { 295 | "bin": "./bin" 296 | }, 297 | "files": [ 298 | "" 299 | ], 300 | "_defaultsLoaded": true, 301 | "dist": { 302 | "shasum": "2be53a1c1241e7a0c2f40272a6efa27df921a180", 303 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.4.tgz" 304 | } 305 | }, 306 | "0.1.5": { 307 | "name": "bejesus-cli", 308 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 309 | "version": "0.1.5", 310 | "homepage": "http://bejes.us/", 311 | "repository": "git://github.com/DanBUK/bejesus-api.git", 312 | "author": { 313 | "name": "Daniel Bartlett", 314 | "email": "dan@f-box.org", 315 | "url": "http://danb-uk.net/" 316 | }, 317 | "bin": { 318 | "bejesus": "bin/bejesus.js" 319 | }, 320 | "engines": { 321 | "node": "*" 322 | }, 323 | "dependencies": { 324 | "nodester-api": "0.1.3" 325 | }, 326 | "_id": "bejesus-cli@0.1.5", 327 | "_engineSupported": true, 328 | "_npmVersion": "0.2.15", 329 | "_nodeVersion": "v0.2.5", 330 | "directories": { 331 | "bin": "./bin" 332 | }, 333 | "files": [ 334 | "" 335 | ], 336 | "_defaultsLoaded": true, 337 | "dist": { 338 | "shasum": "53c2190181a9e623a28df00354e6a953f958e6c0", 339 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.5.tgz" 340 | } 341 | }, 342 | "0.1.6": { 343 | "name": "bejesus-cli", 344 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 345 | "version": "0.1.6", 346 | "homepage": "http://bejes.us/", 347 | "repository": "git://github.com/DanBUK/bejesus-api.git", 348 | "author": { 349 | "name": "Daniel Bartlett", 350 | "email": "dan@f-box.org", 351 | "url": "http://danb-uk.net/" 352 | }, 353 | "bin": { 354 | "bejesus": "bin/bejesus.js" 355 | }, 356 | "engines": { 357 | "node": "*" 358 | }, 359 | "dependencies": { 360 | "nodester-api": "0.1.4" 361 | }, 362 | "_id": "bejesus-cli@0.1.6", 363 | "_engineSupported": true, 364 | "_npmVersion": "0.2.15", 365 | "_nodeVersion": "v0.2.5", 366 | "directories": { 367 | "bin": "./bin" 368 | }, 369 | "files": [ 370 | "" 371 | ], 372 | "_defaultsLoaded": true, 373 | "dist": { 374 | "shasum": "140ea0e1dfb01683eefc5bd7f7364ef35a1fcf57", 375 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.6.tgz" 376 | } 377 | }, 378 | "0.1.7": { 379 | "name": "bejesus-cli", 380 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 381 | "version": "0.1.7", 382 | "homepage": "http://bejes.us/", 383 | "repository": "git://github.com/DanBUK/bejesus-api.git", 384 | "author": { 385 | "name": "Daniel Bartlett", 386 | "email": "dan@f-box.org", 387 | "url": "http://danb-uk.net/" 388 | }, 389 | "bin": { 390 | "bejesus": "bin/bejesus.js" 391 | }, 392 | "engines": { 393 | "node": "*" 394 | }, 395 | "dependencies": { 396 | "nodester-api": "0.1.4" 397 | }, 398 | "_id": "bejesus-cli@0.1.7", 399 | "_engineSupported": true, 400 | "_npmVersion": "0.2.15", 401 | "_nodeVersion": "v0.2.5", 402 | "directories": { 403 | "bin": "./bin" 404 | }, 405 | "files": [ 406 | "" 407 | ], 408 | "_defaultsLoaded": true, 409 | "dist": { 410 | "shasum": "4e045a4f252c60dcb158e41ef5603ecfe9080199", 411 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.1.7.tgz" 412 | } 413 | }, 414 | "0.2.0": { 415 | "name": "bejesus-cli", 416 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 417 | "version": "0.2.0", 418 | "homepage": "http://bejes.us/", 419 | "repository": "git://github.com/nodester/nodester-cli.git", 420 | "author": { 421 | "name": "Daniel Bartlett", 422 | "email": "dan@f-box.org", 423 | "url": "http://danb-uk.net/" 424 | }, 425 | "bin": { 426 | "bejesus": "bin/nodester.js" 427 | }, 428 | "engines": { 429 | "node": "*" 430 | }, 431 | "dependencies": { 432 | "nodester-api": "0.1.4", 433 | "colors": "0.3.0", 434 | "iniparser": "1.0.1" 435 | }, 436 | "_id": "bejesus-cli@0.2.0", 437 | "_engineSupported": true, 438 | "_npmVersion": "0.2.15", 439 | "_nodeVersion": "v0.2.5", 440 | "directories": { 441 | "lib": "./lib", 442 | "bin": "./bin" 443 | }, 444 | "modules": { 445 | "app.js": "lib/app.js", 446 | "appdomain.js": "lib/appdomain.js", 447 | "apps.js": "lib/apps.js", 448 | "config.js": "lib/config.js", 449 | "coupon.js": "lib/coupon.js", 450 | "log.js": "lib/log.js", 451 | "npm.js": "lib/npm.js", 452 | "status.js": "lib/status.js", 453 | "user.js": "lib/user.js" 454 | }, 455 | "files": [ 456 | "" 457 | ], 458 | "_defaultsLoaded": true, 459 | "dist": { 460 | "shasum": "c03666518c4e01313d6368898936d7b2ea0e6568", 461 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.2.0.tgz" 462 | } 463 | }, 464 | "0.2.1": { 465 | "name": "bejesus-cli", 466 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 467 | "version": "0.2.1", 468 | "homepage": "http://bejes.us/", 469 | "repository": "git://github.com/nodester/nodester-cli.git", 470 | "author": { 471 | "name": "Daniel Bartlett", 472 | "email": "dan@f-box.org", 473 | "url": "http://danb-uk.net/" 474 | }, 475 | "bin": { 476 | "bejesus": "bin/nodester.js" 477 | }, 478 | "engines": { 479 | "node": "*" 480 | }, 481 | "dependencies": { 482 | "nodester-api": "0.1.5", 483 | "colors": "0.3.0", 484 | "iniparser": "1.0.1" 485 | }, 486 | "_id": "bejesus-cli@0.2.1", 487 | "_engineSupported": true, 488 | "_npmVersion": "0.2.15", 489 | "_nodeVersion": "v0.2.5", 490 | "directories": { 491 | "lib": "./lib", 492 | "bin": "./bin" 493 | }, 494 | "modules": { 495 | "app.js": "lib/app.js", 496 | "appdomain.js": "lib/appdomain.js", 497 | "apps.js": "lib/apps.js", 498 | "config.js": "lib/config.js", 499 | "coupon.js": "lib/coupon.js", 500 | "log.js": "lib/log.js", 501 | "npm.js": "lib/npm.js", 502 | "status.js": "lib/status.js", 503 | "user.js": "lib/user.js" 504 | }, 505 | "files": [ 506 | "" 507 | ], 508 | "_defaultsLoaded": true, 509 | "dist": { 510 | "shasum": "059a2a63354fa8c5e33c7be57d0861d5dc62ce3e", 511 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.2.1.tgz" 512 | } 513 | }, 514 | "0.2.3": { 515 | "name": "bejesus-cli", 516 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 517 | "version": "0.2.3", 518 | "homepage": "http://bejes.us/", 519 | "repository": "git://github.com/nodester/nodester-cli.git", 520 | "author": { 521 | "name": "Daniel Bartlett", 522 | "email": "dan@f-box.org", 523 | "url": "http://danb-uk.net/" 524 | }, 525 | "bin": { 526 | "bejesus": "bin/nodester.js" 527 | }, 528 | "engines": { 529 | "node": "*" 530 | }, 531 | "dependencies": { 532 | "nodester-api": "0.1.5", 533 | "colors": "0.3.0", 534 | "iniparser": "1.0.1" 535 | }, 536 | "_id": "bejesus-cli@0.2.3", 537 | "_engineSupported": true, 538 | "_npmVersion": "0.2.18", 539 | "_nodeVersion": "v0.4.0", 540 | "directories": { 541 | "lib": "./lib", 542 | "bin": "./bin" 543 | }, 544 | "files": [ 545 | "" 546 | ], 547 | "_defaultsLoaded": true, 548 | "dist": { 549 | "shasum": "72cc581dde6e996721c53300adc6680ee97acb84", 550 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.2.3.tgz" 551 | } 552 | }, 553 | "0.2.4": { 554 | "name": "bejesus-cli", 555 | "description": "A CLI tool to allow interaction with the http://bejes.us/ platform.", 556 | "version": "0.2.4", 557 | "homepage": "http://bejes.us/", 558 | "repository": "git://github.com/nodester/nodester-cli.git", 559 | "author": { 560 | "name": "Daniel Bartlett", 561 | "email": "dan@f-box.org", 562 | "url": "http://danb-uk.net/" 563 | }, 564 | "bin": { 565 | "bejesus": "bin/nodester.js" 566 | }, 567 | "engines": { 568 | "node": "*" 569 | }, 570 | "dependencies": { 571 | "nodester-api": "0.1.5", 572 | "colors": "0.3.0", 573 | "iniparser": "1.0.1" 574 | }, 575 | "_id": "bejesus-cli@0.2.4", 576 | "_engineSupported": true, 577 | "_npmVersion": "0.2.18", 578 | "_nodeVersion": "v0.4.0", 579 | "directories": { 580 | "lib": "./lib", 581 | "bin": "./bin" 582 | }, 583 | "files": [ 584 | "" 585 | ], 586 | "_defaultsLoaded": true, 587 | "dist": { 588 | "shasum": "30d1a1f2aa60ada2cbeccd480e02837a19ef1a99", 589 | "tarball": "http://registry.npmjs.org/bejesus-cli/-/bejesus-cli-0.2.4.tgz" 590 | } 591 | } 592 | }, 593 | "maintainers": [ 594 | { 595 | "name": "DanBUK", 596 | "email": "dan@f-box.org" 597 | } 598 | ], 599 | "time": { 600 | "modified": "2011-02-14T15:56:41.561Z", 601 | "created": "2011-01-29T20:16:37.127Z", 602 | "0.0.1": "2011-01-29T20:16:37.764Z", 603 | "0.0.2": "2011-01-29T21:55:25.491Z", 604 | "0.0.3": "2011-01-30T12:21:27.990Z", 605 | "0.1.0": "2011-01-31T07:57:29.930Z", 606 | "0.1.1": "2011-01-31T11:38:26.970Z", 607 | "0.1.2": "2011-02-01T13:31:08.382Z", 608 | "0.1.3": "2011-02-01T13:49:05.032Z", 609 | "0.1.4": "2011-02-03T15:41:23.687Z", 610 | "0.1.5": "2011-02-05T20:51:11.686Z", 611 | "0.1.6": "2011-02-06T20:41:21.536Z", 612 | "0.1.7": "2011-02-08T13:07:13.471Z", 613 | "0.2.0": "2011-02-12T17:52:35.225Z", 614 | "0.2.1": "2011-02-13T11:59:04.405Z", 615 | "0.2.3": "2011-02-14T11:41:31.104Z", 616 | "0.2.4": "2011-02-14T15:56:41.561Z" 617 | }, 618 | "author": { 619 | "name": "Daniel Bartlett", 620 | "email": "dan@f-box.org", 621 | "url": "http://danb-uk.net/" 622 | }, 623 | "repository": "git://github.com/nodester/nodester-cli.git" 624 | } 625 | } -------------------------------------------------------------------------------- /test/fixtures/fake-changes-stream.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | 3 | function ChangesFeed () {} 4 | 5 | ChangesFeed.prototype.on = function (event, cb) { 6 | return cb() 7 | } 8 | 9 | ChangesFeed.prototype.read = function () { 10 | return JSON.parse( 11 | fs.readFileSync('./test/fixtures/bejesus-cli.json') 12 | ) 13 | } 14 | 15 | module.exports = ChangesFeed 16 | -------------------------------------------------------------------------------- /test/npm-user-download-counts.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | 3 | var TopUsers = require('../') 4 | var fs = require('fs') 5 | var nock = require('nock') 6 | var rimraf = require('rimraf') 7 | 8 | require('chai').should() 9 | require('tap').mochaGlobals() 10 | 11 | rimraf.sync('./output/top-npm-users.json') 12 | rimraf.sync('./output/top-npm-users.md') 13 | 14 | describe('DownloadCounts', function () { 15 | describe('calculate', function () { 16 | it('outputs top-npm-users.json', function (done) { 17 | var downloads = nock('https://api.npmjs.org') 18 | .get('/downloads/point/last-month/bejesus-cli') 19 | .reply(200, { 20 | downloads: 200000, 21 | start: '2015-12-03', 22 | end: '2016-01-01', 23 | package: 'bejesus-cli' 24 | }) 25 | var dc = new TopUsers({ 26 | ChangesStream: require('./fixtures/fake-changes-stream'), 27 | saveInterval: 25 28 | }) 29 | 30 | dc.calculate() 31 | 32 | setTimeout(function () { 33 | downloads.done() 34 | dc.stop() 35 | 36 | var topUsers = JSON.parse(fs.readFileSync('./output/top-npm-users.json')) 37 | topUsers.DanBUK.should.equal(200000) 38 | 39 | return done() 40 | }, 200) 41 | }) 42 | }) 43 | 44 | describe('render', function () { 45 | it('renders top-npm-users.md', function (done) { 46 | var dc = new TopUsers() 47 | dc.render() 48 | 49 | var content = fs.readFileSync('./output/top-npm-users.md', 'utf-8') 50 | content.should.match(/1.*DanBUK.*200,?000/) 51 | 52 | return done() 53 | }) 54 | }) 55 | }) 56 | -------------------------------------------------------------------------------- /top-npm-users.md.mustache: -------------------------------------------------------------------------------- 1 | # npm Users By Downloads ([git.io/npm-top](http://git.io/npm-top)) 2 | 3 | ---------- 4 | 5 | npm users sorted by the monthly downloads of their modules, for the range _{{start}}_ until _{{end}}_. 6 | 7 | Metrics are calculated using [top-npm-users](https://github.com/bcoe/top-npm-users). 8 | 9 | | **#** | User | Downloads | 10 | | ----- | ---- | --------- | 11 | {{#users}} 12 | |**{{index}}**|[{{name}}](https://www.npmjs.com/~{{name}})|{{downloads}}| 13 | {{/users}} 14 | --------------------------------------------------------------------------------