├── .gitignore ├── example-output.png ├── LICENSE ├── package.json ├── bin └── package-config-checker.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /example-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/insin/package-config-checker/HEAD/example-output.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Jonny Buchanan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-config-checker", 3 | "version": "2.0.1", 4 | "description": "Tells you things about your dependencies and transitive dependencies", 5 | "main": "index.js", 6 | "bin": { 7 | "package-config-checker": "bin/package-config-checker.js" 8 | }, 9 | "files": [ 10 | "bin" 11 | ], 12 | "scripts": { 13 | "lint": "eslint bin" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/insin/package-config-checker.git" 18 | }, 19 | "keywords": [ 20 | "npm", 21 | "package", 22 | "files", 23 | "npmignore", 24 | "checker" 25 | ], 26 | "author": "Jonny Buchanan ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/insin/package-config-checker/issues" 30 | }, 31 | "homepage": "https://github.com/insin/package-config-checker#readme", 32 | "dependencies": { 33 | "chalk": "1.1.3", 34 | "debug": "2.6.0", 35 | "figures": "2.0.0", 36 | "file-exists": "2.0.0", 37 | "minimist": "1.2.0", 38 | "read-installed": "4.0.3" 39 | }, 40 | "devDependencies": { 41 | "eslint-config-jonnybuchanan": "4.8.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bin/package-config-checker.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var path = require('path') 4 | 5 | var chalk = require('chalk') 6 | var cyan = chalk.cyan 7 | var green = chalk.green 8 | var red = chalk.red 9 | var yellow = chalk.yellow 10 | var debug = require('debug') 11 | var fileExists = require('file-exists') 12 | var figures = require('figures') 13 | var parseArgs = require('minimist') 14 | var readInstalled = require('read-installed') 15 | 16 | var pkg = require('../package.json') 17 | 18 | var debugLog = debug('package-config-checker:log') 19 | 20 | var args = parseArgs(process.argv.slice(2), { 21 | alias: { 22 | d: 'depth', 23 | f: 'files', 24 | h: 'help', 25 | r: 'recent' 26 | }, 27 | boolean: ['files', 'help', 'recent'] 28 | }) 29 | 30 | if (args.help) { 31 | console.log([ 32 | 'Usage: ' + green('package-config-checker') + ' ' + yellow('') + ' ' + cyan('[options]'), 33 | '', 34 | 'Options:', 35 | ' ' + cyan('-h, --help') + ' display this help message', 36 | ' ' + cyan('-d, --depth') + ' max depth for checking dependency tree ' + cyan('(default: ∞)'), 37 | '', 38 | 'Show:', 39 | ' ' + yellow('-f, --files') + ' show presence of files config or .npmignore', 40 | ' ' + yellow('-r, --recent') + ' show recently updated dependencies', 41 | '', 42 | pkg.name + '@' + pkg.version + ' ' + path.join(__dirname, '..') 43 | ].join('\n')) 44 | process.exit(0) 45 | } 46 | 47 | if (!args.files && !args.recent) { 48 | console.error("You haven't specified anything to show.") 49 | process.exit(1) 50 | } 51 | 52 | var readInstalledOptions = { 53 | log: debugLog 54 | } 55 | 56 | if (args.depth != null) { 57 | readInstalledOptions.depth = args.depth 58 | } 59 | 60 | readInstalled(process.cwd(), readInstalledOptions, function(err, json) { 61 | if (err) { 62 | console.error(red('Error reading installed packages: ' + err.message)) 63 | console.error(err.stack) 64 | process.exit(1) 65 | } 66 | check(json, {}, '') 67 | if (args.recent) { 68 | publishTimes.sort().reverse() 69 | console.log([ 70 | '10 most recently published packages:', 71 | '', 72 | publishTimes.slice(0, 10).join('\n') 73 | ].join('\n')) 74 | } 75 | }) 76 | 77 | var publishTimes = [] 78 | 79 | function check(json, seen, prefix) { 80 | if (seen[json._id]) { 81 | return 82 | } 83 | 84 | if (json._npmOperationalInternal) { 85 | var published = /tgz_(\d+)_/.exec(json._npmOperationalInternal.tmp)[1] 86 | publishTimes.push(published + ' ' + json._id + ' - ' + new Date(Number(published))) 87 | } 88 | 89 | if (args.files) { 90 | if (json.files) { 91 | console.log(prefix + green(figures.tick + ' ' + json._id + ' [files]')) 92 | } 93 | else if (json.realPath && fileExists(path.join(json.realPath, '.npmignore'))) { 94 | console.log(prefix + green(figures.tick + ' ' + json._id + ' [.npmignore]')) 95 | } 96 | else { 97 | console.log(prefix + red(figures.cross + ' ' + json._id)) 98 | } 99 | } 100 | 101 | seen[json._id] = true 102 | 103 | if (json.dependencies) { 104 | Object.keys(json.dependencies).forEach(function(name) { 105 | check(json.dependencies[name], seen, prefix + ' ') 106 | }) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Package Config Checker 2 | 3 | [![npm package][npm-badge]][npm] 4 | 5 | Tells you things about your dependencies and transitive dependencies. 6 | 7 | ## Usage 8 | 9 | ``` 10 | npm install -g package-config-checker 11 | ``` 12 | ``` 13 | Usage: package-config-checker [options] 14 | 15 | Options: 16 | -h, --help display this help message 17 | -d, --depth max depth for checking dependency tree (default: ∞) 18 | 19 | Show: 20 | -f, --files show presence of files config or .npmignore 21 | -r, --recent show recently updated dependencies 22 | ``` 23 | 24 | ## Show Flags 25 | 26 | You must specify at least one thing to show. 27 | 28 | ### `-f, --files` 29 | 30 | Checks if your npm dependencies (and transitive dependencies) have [`files` config in `package.json`](https://docs.npmjs.com/files/package.json#files) or have an [`.npmignore` file](https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package) to avoid including unnecessary files when your module is being packaged for publishing to the npm registry. 31 | 32 | Since [npm automatically whitelists certain essential files and blacklists common files which should not be included in module packages](https://docs.npmjs.com/files/package.json#files) (such as source control directories, `npm-debug.log` and `.DS_Store`), submitting a Pull Request to one of your dependencies to add a `files` whitelist to its `package.json` is a quick and easy way to reduce the size of your - and everybody else's - `npm install`. 33 | 34 | ### `-r, --recent` 35 | 36 | Shows the 10 most recently published dependencies - use this if you have a hunch you just got broken by a transitive dependency. 37 | 38 | ## Example 39 | 40 | Checking `package-config-checker`'s own direct dependencies as an example: 41 | 42 | ``` 43 | $ package-config-checker -f -d 0 44 | ``` 45 | ![](example-output.png) 46 | 47 | `minimist@1.2.0` has been flagged as not having any configuration to control publishing. 48 | 49 | Let's look at what was included in its npm packge: 50 | 51 | ``` 52 | $ ls -a node_modules/minimist/ 53 | ./ .travis.yml index.js package.json test/ 54 | ../ example/ LICENSE readme.markdown 55 | 56 | ``` 57 | 58 | It includes `example/` and `test/` directories, and a Travis CI config file, which most likely aren't required to use minimist. These take up an additional 18.2 KB of space, which isn't really a big deal in absolute terms. 59 | 60 | Let's package the module up again and rename the resulting file so we can compare later. 61 | 62 | ``` 63 | $ cd node_modules/minimist/ 64 | $ npm pack 65 | minimist-1.2.0.tgz 66 | $ mv minimist-1.2.0.tgz minimist-1.2.0-pre.tgz 67 | ``` 68 | 69 | Now let's add suitable `files` config to `package.json`: 70 | 71 | ```json 72 | "files": [ 73 | "index.js" 74 | ], 75 | ``` 76 | 77 | If we repackage the module, npm will now use the `files` config. 78 | 79 | Listing the contents of the new package shows an example of the default files npm whitelists in addition to the module-specific whitelist we provided: 80 | 81 | ``` 82 | $ npm pack 83 | minimist-1.2.0.tgz 84 | $ tar -tf minimist-1.2.0.tgz 85 | package/package.json 86 | package/LICENSE 87 | package/index.js 88 | package/readme.markdown 89 | ``` 90 | 91 | Now we can compare the before and after size of the package which would be published to npm: 92 | 93 | ``` 94 | $ ls *.tgz -l | awk '{print $9,$5}' 95 | minimist-1.2.0.tgz 4300 96 | minimist-1.2.0-pre.tgz 7984 97 | ``` 98 | 99 | That's approximately 3.6 KB less to download. 100 | 101 | The bandwith and `node_modules/` savings in this example are fairly insignificant per install, but at the time of writing minimist has been downloaded from npm *27,095,636* times in the last month. 102 | 103 | The reduced package size would have resulted in a *93GB* bandwith saving for the npm registry for that number of downloads. 104 | 105 | Now that we've done the research, the final step is to [create a Pull Request](https://github.com/substack/minimist/pull/88) with the packaging config changes. 106 | 107 | You can do this by editing `package.json` directly from the GitHub UI, which will fork the project for you in the background and let you create a Pull Request at the same time. 108 | 109 | ## MIT Licensed 110 | 111 | [npm-badge]: https://img.shields.io/npm/v/package-config-checker.png 112 | [npm]: https://www.npmjs.org/package/package-config-checker 113 | --------------------------------------------------------------------------------