Repository: dylang/npm-check
Branch: master
Commit: 72eac3b25a36
Files: 30
Total size: 58.1 KB
Directory structure:
gitextract_76r69cho/
├── .babelrc
├── .editorconfig
├── .gitignore
├── .travis.yml
├── .vscode/
│ └── launch.json
├── README.md
├── appveyor.yml
├── bin/
│ └── cli.js
├── index.d.ts
├── lib/
│ ├── cli.js
│ ├── in/
│ │ ├── best-guess-homepage.js
│ │ ├── create-package-summary.js
│ │ ├── find-module-path.js
│ │ ├── get-installed-packages.js
│ │ ├── get-latest-from-registry.js
│ │ ├── get-unused-packages.js
│ │ ├── index.js
│ │ └── read-package-json.js
│ ├── index.js
│ ├── out/
│ │ ├── emoji.js
│ │ ├── install-packages.js
│ │ ├── interactive-update.js
│ │ ├── static-output.js
│ │ └── update-all.js
│ └── state/
│ ├── debug.js
│ ├── init.js
│ └── state.js
├── license
├── package.json
└── renovate.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
"es2015"
],
"plugins": [
"transform-runtime",
"transform-object-rest-spread"
]
}
================================================
FILE: .editorconfig
================================================
# Get the plugin for your editor and your
# tab settings will be set automatically.
# http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# Indentation override for all JS under lib directory
[*.js]
indent_size = 4
================================================
FILE: .gitignore
================================================
/.idea/
/node_modules/
/*.log
/lib-es5/
================================================
FILE: .travis.yml
================================================
sudo: false
language: node_js
os:
- linux
- osx
node_js:
- 12.22.12
- 10.24.1
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "cli",
"program": "${workspaceFolder}/lib/cli.js",
"args": ["--debug"]
}
]
}
================================================
FILE: README.md
================================================
npm-check
=========
[](https://travis-ci.org/dylang/npm-check)
[](http://badge.fury.io/js/npm-check)
[]()
> Check for outdated, incorrect, and unused dependencies.
<img width="796" alt="npm-check -u" src="https://cloud.githubusercontent.com/assets/51505/9569917/96947fea-4f48-11e5-9783-2d78077256f2.png">
### Features
* Tells you what's out of date.
* Provides a link to the package's documentation so you can decide if you want the update.
* Kindly informs you if a dependency is not being used in your code.
* Works on your globally installed packages too, via `-g`.
* **Interactive Update** for less typing and fewer typos, via `-u`.
* Supports public and private [@scoped/packages](https://docs.npmjs.com/getting-started/scoped-packages).
* Supports ES6-style [`import from`](http://exploringjs.com/es6/ch_modules.html) syntax.
* Upgrades your modules using your installed version of npm, including the new `npm@3`, so dependencies go where you expect them.
* Works with any public npm registry, [private registries](https://www.npmjs.com/enterprise), and alternate registries like [Sinopia](https://github.com/rlidwka/sinopia).
* Does not query registries for packages with `private: true` in their package.json.
* Emoji in a command-line app, because command-line apps can be fun too.
* Works with `npm@2` and `npm@3`, as well as newer alternative installers like `ied` and `pnpm`.
### Requirements
* Node >= 10.9.0
### On the command line
This is the easiest way to use `npm-check`.
### Install
```bash
npm install -g npm-check
```
### Use
```bash
npm-check
```
<img width="882" alt="npm-check" src="https://cloud.githubusercontent.com/assets/51505/9569919/99c2412a-4f48-11e5-8c65-e9b6530ee991.png">
The result should look like the screenshot, or something nice when your packages are all up-to-date and in use.
When updates are required it will return a non-zero response code that you can use in your CI tools.
### Options
```
Usage
$ npm-check <path> <options>
Path
Where to check. Defaults to current directory. Use -g for checking global modules.
Options
-u, --update Interactive update.
-y, --update-all Uninteractive update. Apply all updates without prompting.
-g, --global Look at global modules.
-s, --skip-unused Skip check for unused packages.
-p, --production Skip devDependencies.
-d, --dev-only Look at devDependencies only (skip dependencies).
-i, --ignore Ignore dependencies based on succeeding glob.
-E, --save-exact Save exact version (x.y.z) instead of caret (^x.y.z) in package.json.
--specials List of depcheck specials to include in check for unused dependencies.
--no-color Force or disable color output.
--no-emoji Remove emoji support. No emoji in default in CI environments.
--debug Show debug output. Throw in a gist when creating issues on github.
Examples
$ npm-check # See what can be updated, what isn't being used.
$ npm-check ../foo # Check another path.
$ npm-check -gu # Update globally installed modules by picking which ones to upgrade.
```

#### `-u, --update`
Show an interactive UI for choosing which modules to update.
Automatically updates versions referenced in the `package.json`.
_Based on recommendations from the `npm` team, `npm-check` only updates using `npm install`, not `npm update`.
To avoid using more than one version of `npm` in one directory, `npm-check` will automatically install updated modules
using the version of `npm` installed globally._
<img width="669" alt="npm-check -g -u" src="https://cloud.githubusercontent.com/assets/51505/9569921/9ca3aeb0-4f48-11e5-95ab-6fdb88124007.png">
##### Update using [ied](https://github.com/alexanderGugel/ied) or [pnpm](https://github.com/rstacruz/pnpm)
Set environment variable `NPM_CHECK_INSTALLER` to the name of the installer you wish to use.
```bash
NPM_CHECK_INSTALLER=pnpm npm-check -u
## pnpm install --save-dev foo@version --color=always
```
You can also use this for dry-run testing:
```bash
NPM_CHECK_INSTALLER=echo npm-check -u
```
#### `-y, --update-all`
Updates your dependencies like `--update`, just without any prompt. This is especially useful if you want to automate your dependency updates with `npm-check`.
#### `-g, --global`
Check the versions of your globally installed packages.
If the value of `process.env.NODE_PATH` is set, it will override the default path of global node_modules returned by package [`global-modules`](https://www.npmjs.com/package/global-modules).
_Tip: Use `npm-check -u -g` to do a safe interactive update of global modules, including npm itself._
#### `-s, --skip-unused`
By default `npm-check` will let you know if any of your modules are not being used by looking at `require` statements
in your code.
This option will skip that check.
This is enabled by default when using `global` or `update`.
#### `-p, --production`
By default `npm-check` will look at packages listed as `dependencies` and `devDependencies`.
This option will let it ignore outdated and unused checks for packages listed as `devDependencies`.
#### `-d, --dev-only`
Ignore `dependencies` and only check `devDependencies`.
This option will let it ignore outdated and unused checks for packages listed as `dependencies`.
#### `-i, --ignore`
Ignore dependencies that match specified glob.
`$ npm-check -i babel-*` will ignore all dependencies starting with 'babel-'.
#### `-E, --save-exact`
Install packages using `--save-exact`, meaning exact versions will be saved in package.json.
Applies to both `dependencies` and `devDependencies`.
#### `--specials`
Check special (e.g. config) files when looking for unused dependencies.
`$ npm-check --specials=bin,webpack` will look in the `scripts` section of package.json and in webpack config.
See [https://github.com/depcheck/depcheck#special](https://github.com/depcheck/depcheck#special) for more information.
#### `--color, --no-color`
Enable or disable color support.
By default `npm-check` uses colors if they are available.
#### `--emoji, --no-emoji`
Enable or disable emoji support. Useful for terminals that don't support them. Automatically disabled in CI servers.
#### `--spinner, --no-spinner`
Enable or disable the spinner. Useful for terminals that don't support them. Automatically disabled in CI servers.
### API
The API is here in case you want to wrap this with your CI toolset.
```js
const npmCheck = require('npm-check');
npmCheck(options)
.then(currentState => console.log(currentState.get('packages')));
```
#### `update`
* Interactive update.
* default is `false`
#### `global`
* Check global modules.
* default is `false`
* `cwd` is automatically set with this option.
#### `skipUnused`
* Skip checking for unused packages.
* default is `false`
#### `ignoreDev`
* Ignore `devDependencies`.
* This is called `--production` on the command line to match `npm`.
* default is `false`
#### `devOnly`
* Ignore `dependencies` and only check `devDependencies`.
* default is `false`
#### `ignore`
* Ignore dependencies that match specified glob.
* default is `[]`
#### `saveExact`
* Update package.json with exact version `x.y.z` instead of semver range `^x.y.z`.
* default is `false`
#### `debug`
* Show debug output. Throw in a gist when creating issues on github.
* default is `false`
#### `cwd`
* Override where `npm-check` checks.
* default is `process.cwd()`
#### `specials`
* List of [`depcheck`](https://github.com/depcheck/depcheck) special parsers to include.
* default is `''`
#### `currentState`
The result of the promise is a `currentState` object, look in [state.js](lib/state/state.js) to see how it works.
You will probably want `currentState.get('packages')` to get an array of packages and the state of each of them.
Each item in the array will look like the following:
```js
{
moduleName: 'lodash', // name of the module.
homepage: 'https://lodash.com/', // url to the home page.
regError: undefined, // error communicating with the registry
pkgError: undefined, // error reading the package.json
latest: '4.7.0', // latest according to the registry.
installed: '4.6.1', // version installed
isInstalled: true, // Is it installed?
notInstalled: false, // Is it installed?
packageWanted: '4.7.0', // Requested version from the package.json.
packageJson: '^4.6.1', // Version or range requested in the parent package.json.
devDependency: false, // Is this a devDependency?
usedInScripts: undefined, // Array of `scripts` in package.json that use this module.
mismatch: false, // Does the version installed not match the range in package.json?
semverValid: '4.6.1', // Is the installed version valid semver?
easyUpgrade: true, // Will running just `npm install` upgrade the module?
bump: 'minor', // What kind of bump is required to get the latest, such as patch, minor, major.
unused: false // Is this module used in the code?
},
```
You will also see this if you use `--debug` on the command line.
### RC File Support
Additional options can be sent to the depcheck process. See [depcheck API](https://github.com/depcheck/depcheck#api). Create a .npmcheckrc{.json,.yml,.js} file and set the depcheck options under depcheck property.
For example, to skip packages for unused check, but still want them in the outdated check (so can't use the --ignore option):
```
# .npmcheckrc
depcheck:
ignoreMatches: ["replace-in-file","snyk","sonarqube-scanner"]
```
### Inspiration
* [npm outdated](https://docs.npmjs.com/cli/v7/commands/npm-outdated) - awkward output, requires --depth=0 to be grokable.
* [david](https://github.com/alanshaw/david) - does not work with private registries.
* [update-notifier](https://github.com/yeoman/update-notifier) - for single modules, not everything in package.json.
* [depcheck](https://github.com/depcheck/depcheck) - only part of the puzzle. npm-check uses depcheck.
### About the Author
Hi! Thanks for checking out this project! My name is **Dylan Greene**. When not overwhelmed with my two young kids I enjoy contributing
to the open source community. I'm also a tech lead at [Opower](https://opower.com/). [](https://github.com/dylang) [](https://twitter.com/dylang)
Here's some of my other Node projects:
| Name | Description | npm Downloads |
|---|---|---|
| [`grunt‑notify`](https://github.com/dylang/grunt-notify) | Automatic desktop notifications for Grunt errors and warnings. Supports OS X, Windows, Linux. | [](https://www.npmjs.org/package/grunt-notify) |
| [`shortid`](https://github.com/dylang/shortid) | Amazingly short non-sequential url-friendly unique id generator. | [](https://www.npmjs.org/package/shortid) |
| [`space‑hogs`](https://github.com/dylang/space-hogs) | Discover surprisingly large directories from the command line. | [](https://www.npmjs.org/package/space-hogs) |
| [`rss`](https://github.com/dylang/node-rss) | RSS feed generator. Add RSS feeds to any project. Supports enclosures and GeoRSS. | [](https://www.npmjs.org/package/rss) |
| [`grunt‑prompt`](https://github.com/dylang/grunt-prompt) | Interactive prompt for your Grunt config using console checkboxes, text input with filtering, password fields. | [](https://www.npmjs.org/package/grunt-prompt) |
| [`xml`](https://github.com/dylang/node-xml) | Fast and simple xml generator. Supports attributes, CDATA, etc. Includes tests and examples. | [](https://www.npmjs.org/package/xml) |
| [`changelog`](https://github.com/dylang/changelog) | Command line tool (and Node module) that generates a changelog in color output, markdown, or json for modules in npmjs.org's registry as well as any public github.com repo. | [](https://www.npmjs.org/package/changelog) |
| [`grunt‑attention`](https://github.com/dylang/grunt-attention) | Display attention-grabbing messages in the terminal | [](https://www.npmjs.org/package/grunt-attention) |
| [`observatory`](https://github.com/dylang/observatory) | Beautiful UI for showing tasks running on the command line. | [](https://www.npmjs.org/package/observatory) |
| [`anthology`](https://github.com/dylang/anthology) | Module information and stats for any @npmjs user | [](https://www.npmjs.org/package/anthology) |
| [`grunt‑cat`](https://github.com/dylang/grunt-cat) | Echo a file to the terminal. Works with text, figlets, ascii art, and full-color ansi. | [](https://www.npmjs.org/package/grunt-cat) |
_This list was generated using [anthology](https://github.com/dylang/anthology)._
### License
Copyright (c) 2016 Dylan Greene, contributors.
Released under the [MIT license](https://tldrlegal.com/license/mit-license).
Screenshots are [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) (Attribution-ShareAlike).
================================================
FILE: appveyor.yml
================================================
environment:
matrix:
- nodejs_version: 12
- nodejs_version: 10
install:
- ps: Install-Product node $env:nodejs_version
- npm install
- set CI=true
test_script:
- node --version
- npm --version
- npm run lint
- "node lib\\cli.js || ver > null"
- "echo Exit code: %errorlevel%"
build: off
shallow_clone: true
clone_depth: 1
version: '{build}'
matrix:
fast_finish: true
================================================
FILE: bin/cli.js
================================================
#!/usr/bin/env node
var isEs2015;
try {
isEs2015 = new Function('() => {}');
} catch (e) {
isEs2015 = false;
}
isEs2015 ? require('../lib/cli') : require('../lib-es5/cli');
================================================
FILE: index.d.ts
================================================
declare module NpmCheck {
interface INpmCheckOptions {
global?: boolean;
update?: boolean;
skipUnused?: boolean;
devOnly?: boolean;
ignoreDev?: boolean;
cwd?: string;
saveExact?: boolean;
currentState?: Object;
}
type INpmCheckGetSetValues = "packages" | "debug" | "global" | "cwd" | "cwdPackageJson" | "emoji";
type INpmVersionBumpType = "patch" | "minor" | "major" | "prerelease" | "build" | "nonSemver" | null;
interface INpmCheckCurrentState {
get: (key: INpmCheckGetSetValues) => INpmCheckPackage[];
set: (key: INpmCheckGetSetValues, val: any) => void;
}
interface INpmCheckPackage {
moduleName: string; // name of the module.
homepage: string; // url to the home page.
regError: any; // error communicating with the registry
pkgError: any; // error reading the package.json
latest: string; // latest according to the registry.
installed: string; // version installed
isInstalled: boolean; // Is it installed?
notInstalled: boolean; // Is it installed?
packageWanted: string; // Requested version from the package.json.
packageJson: string; // Version or range requested in the parent package.json.
devDependency: boolean; // Is this a devDependency?
usedInScripts: undefined | string[], // Array of `scripts` in package.json that use this module.
mismatch: boolean; // Does the version installed not match the range in package.json?
semverValid: string; // Is the installed version valid semver?
easyUpgrade: boolean; // Will running just `npm install` upgrade the module?
bump: INpmVersionBumpType; // What kind of bump is required to get the latest
unused: boolean; // Is this module used in the code?
}
//The default function returns a promise
export default function(options: INpmCheckOptions): {
then(stateFn: (state: INpmCheckCurrentState) => void): void;
};
}
declare module "npm-check" {
export = NpmCheck.default;
}
================================================
FILE: lib/cli.js
================================================
#!/usr/bin/env node
'use strict';
const meow = require('meow');
const updateNotifier = require('update-notifier');
const isCI = require('is-ci');
const createCallsiteRecord = require('callsite-record');
const pkg = require('../package.json');
const npmCheck = require('./index');
const staticOutput = require('./out/static-output');
const interactiveUpdate = require('./out/interactive-update');
const updateAll = require('./out/update-all');
const debug = require('./state/debug');
const pkgDir = require('pkg-dir');
const detectPreferredPM = require('preferred-pm');
updateNotifier({pkg}).notify();
/* eslint-disable indent */
const cli = meow(`
Usage
$ npm-check <path> <options>
Path
Where to check. Defaults to current directory. Use -g for checking global modules.
Options
-u, --update Interactive update.
-y, --update-all Uninteractive update. Apply all updates without prompting.
-g, --global Look at global modules.
-s, --skip-unused Skip check for unused packages.
-p, --production Skip devDependencies.
-d, --dev-only Look at devDependencies only (skip dependencies).
-i, --ignore Ignore dependencies based on succeeding glob.
-E, --save-exact Save exact version (x.y.z) instead of caret (^x.y.z) in package.json.
--specials List of depcheck specials to include in check for unused dependencies.
--no-color Force or disable color output.
--no-emoji Remove emoji support. No emoji in default in CI environments.
--debug Debug output. Throw in a gist when creating issues on github.
Examples
$ npm-check # See what can be updated, what isn't being used.
$ npm-check ../foo # Check another path.
$ npm-check -gu # Update globally installed modules by picking which ones to upgrade.
`,
{
flags: {
update: {
type: 'boolean',
alias: 'u'
},
updateAll: {
type: 'boolean',
alias: 'y'
},
global: {
type: 'boolean',
alias: 'g'
},
skipUnused: {
type: 'boolean',
alias: 's'
},
production: {
type: 'boolean',
alias: 'p'
},
devOnly: {
type: 'boolean',
alias: 'd'
},
saveExact: {
type: 'boolean',
alias: 'E'
},
ignore: {
type: 'string',
alias: 'i'
},
specials: {
type: 'string'
},
color: {
type: 'boolean'
},
emoji: {
type: 'boolean',
default: !isCI
},
debug: {
type: 'boolean'
},
spinner: {
type: 'boolean',
default: !isCI
}
}
});
/* eslint-enable indent */
const options = {
cwd: cli.input[0] || pkgDir.sync() || process.cwd(),
update: cli.flags.update,
updateAll: cli.flags.updateAll,
global: cli.flags.global,
skipUnused: cli.flags.skipUnused,
ignoreDev: cli.flags.production,
devOnly: cli.flags.devOnly,
saveExact: cli.flags.saveExact,
specials: cli.flags.specials,
emoji: cli.flags.emoji,
installer: process.env.NPM_CHECK_INSTALLER || 'auto',
debug: cli.flags.debug,
spinner: cli.flags.spinner,
ignore: cli.flags.ignore
};
if (options.debug) {
debug('cli.flags', cli.flags);
debug('cli.input', cli.input);
}
Promise.resolve()
.then(() => {
return options.installer === 'auto' ?
detectPreferredInstaller(options.cwd) :
options.installer;
})
.then(installer => {
options.installer = installer;
return npmCheck(options);
})
.then(currentState => {
currentState.inspectIfDebugMode();
if (options.updateAll) {
return updateAll(currentState);
}
if (options.update) {
return interactiveUpdate(currentState);
}
return staticOutput(currentState);
})
.catch(error => {
console.log(error.message);
if (options.debug) {
console.log(createCallsiteRecord(error).renderSync());
} else {
console.log('For more detail, add `--debug` to the command');
}
process.exit(1);
});
const SUPPORTED_INSTALLERS = new Set(['npm', 'pnpm', 'ied', 'yarn']);
async function detectPreferredInstaller(cwd) {
const preferredPM = await detectPreferredPM(cwd);
return preferredPM && SUPPORTED_INSTALLERS.has(preferredPM.name) ? preferredPM.name : 'npm';
}
================================================
FILE: lib/in/best-guess-homepage.js
================================================
'use strict';
const gitUrl = require('giturl');
function bestGuessHomepage(data) {
if (!data) {
return false;
}
const packageDataForLatest = data.versions[data['dist-tags'].latest];
return packageDataForLatest.homepage ||
packageDataForLatest.bugs && packageDataForLatest.bugs.url && gitUrl.parse(packageDataForLatest.bugs.url.trim()) ||
packageDataForLatest.repository && packageDataForLatest.repository.url && gitUrl.parse(packageDataForLatest.repository.url.trim());
}
module.exports = bestGuessHomepage;
================================================
FILE: lib/in/create-package-summary.js
================================================
'use strict';
const readPackageJson = require('./read-package-json');
const getLatestFromRegistry = require('./get-latest-from-registry');
const findModulePath = require('./find-module-path');
const _ = require('lodash');
const semverDiff = require('semver-diff');
const pathExists = require('path-exists');
const path = require('path');
const semver = require('semver');
const minimatch = require('minimatch');
function createPackageSummary(moduleName, currentState) {
const cwdPackageJson = currentState.get('cwdPackageJson');
const modulePath = findModulePath(moduleName, currentState);
const packageIsInstalled = pathExists.sync(modulePath);
const modulePackageJson = readPackageJson(path.join(modulePath, 'package.json'));
// Ignore private packages
const isPrivate = Boolean(modulePackageJson.private);
if (isPrivate) {
return false;
}
// Ignore packages that are using github or file urls
const packageJsonVersion = cwdPackageJson.dependencies[moduleName] ||
cwdPackageJson.devDependencies[moduleName] ||
currentState.get('globalPackages')[moduleName];
if (packageJsonVersion && !semver.validRange(packageJsonVersion)) {
return false;
}
// Ignore specified '--ignore' package globs
const ignore = currentState.get('ignore');
if (ignore) {
const ignoreMatch = Array.isArray(ignore) ? ignore.some(ignoredModule => minimatch(moduleName, ignoredModule)) : minimatch(moduleName, ignore);
if (ignoreMatch) {
return false;
}
}
const unusedDependencies = currentState.get('unusedDependencies');
const missingFromPackageJson = currentState.get('missingFromPackageJson');
function foundIn(files) {
if (!files) {
return;
}
return 'Found in: ' + files.map(filepath => filepath.replace(currentState.get('cwd'), ''))
.join(', ');
}
return getLatestFromRegistry(moduleName)
.then(fromRegistry => {
const installedVersion = modulePackageJson.version;
const latest = installedVersion && fromRegistry.latest && fromRegistry.next && semver.gt(installedVersion, fromRegistry.latest) ? fromRegistry.next : fromRegistry.latest;
const versions = fromRegistry.versions || [];
const versionWanted = semver.maxSatisfying(versions, packageJsonVersion);
const versionToUse = installedVersion || versionWanted;
const usingNonSemver = semver.valid(latest) && semver.lt(latest, '1.0.0-pre');
const bump = semver.valid(latest) &&
semver.valid(versionToUse) &&
(usingNonSemver && semverDiff(versionToUse, latest) ? 'nonSemver' : semverDiff(versionToUse, latest));
const unused = _.includes(unusedDependencies, moduleName);
return {
// info
moduleName: moduleName,
homepage: fromRegistry.homepage,
regError: fromRegistry.error,
pkgError: modulePackageJson.error,
// versions
latest: latest,
installed: versionToUse,
isInstalled: packageIsInstalled,
notInstalled: !packageIsInstalled,
packageWanted: versionWanted,
packageJson: packageJsonVersion,
// Missing from package json
notInPackageJson: foundIn(missingFromPackageJson[moduleName]),
// meta
devDependency: _.has(cwdPackageJson.devDependencies, moduleName),
usedInScripts: _.findKey(cwdPackageJson.scripts, script => {
return script.indexOf(moduleName) !== -1;
}),
mismatch: semver.validRange(packageJsonVersion) &&
semver.valid(versionToUse) &&
!semver.satisfies(versionToUse, packageJsonVersion),
semverValid:
semver.valid(versionToUse),
easyUpgrade: semver.validRange(packageJsonVersion) &&
semver.valid(versionToUse) &&
semver.satisfies(latest, packageJsonVersion) &&
bump !== 'major',
bump: bump,
unused: unused
};
});
}
module.exports = createPackageSummary;
================================================
FILE: lib/in/find-module-path.js
================================================
'use strict';
const Module = require('module');
const path = require('path');
const pathExists = require('path-exists');
/**
* Searches the directory hierarchy to return the path to the requested node module.
* If the module can't be found, returns the initial (deepest) tried path.
*/
function findModulePath(moduleName, currentState) {
const cwd = currentState.get('cwd');
if (currentState.get('global')) {
return path.join(cwd, moduleName);
}
// Module._nodeModulePaths does not include some places the node module resolver searches, such as
// the global prefix or other special directories. This is desirable because if a module is missing
// in the project directory we want to be sure to report it as missing.
// We can't use require.resolve because it fails if the module doesn't have an entry point.
const nodeModulesPaths = Module._nodeModulePaths(cwd);
const possibleModulePaths = nodeModulesPaths.map(x => path.join(x, moduleName));
const modulePath = possibleModulePaths.find(pathExists.sync);
// if no existing path was found, return the first tried path anyway
return modulePath || path.join(cwd, moduleName);
}
module.exports = findModulePath;
================================================
FILE: lib/in/get-installed-packages.js
================================================
'use strict';
const _ = require('lodash');
const globby = require('globby');
const readPackageJson = require('./read-package-json');
const path = require('path');
module.exports = function (cwd) {
const GLOBBY_PACKAGE_JSON = '{*/package.json,@*/*/package.json}';
const installedPackages = globby.sync(GLOBBY_PACKAGE_JSON, {cwd: cwd});
return _(installedPackages)
.map(pkgPath => {
const pkg = readPackageJson(path.resolve(cwd, pkgPath));
return [pkg.name, pkg.version];
})
.fromPairs()
.valueOf();
};
================================================
FILE: lib/in/get-latest-from-registry.js
================================================
'use strict';
const _ = require('lodash');
const bestGuessHomepage = require('./best-guess-homepage');
const semver = require('semver');
const packageJson = require('package-json');
const cpuCount = require('os').cpus().length;
const throat = require('throat')(cpuCount);
function getNpmInfo(packageName) {
return throat(() => packageJson(packageName, { fullMetadata: true, allVersions: true }))
.then(rawData => {
const CRAZY_HIGH_SEMVER = '8000.0.0';
const sortedVersions = _(rawData.versions)
.keys()
.remove(_.partial(semver.gt, CRAZY_HIGH_SEMVER))
.sort(semver.compare)
.valueOf();
const latest = rawData['dist-tags'].latest;
const next = rawData['dist-tags'].next;
const latestStableRelease = semver.satisfies(latest, '*') ?
latest :
semver.maxSatisfying(sortedVersions, '*');
return {
latest: latestStableRelease,
next: next,
versions: sortedVersions,
homepage: bestGuessHomepage(rawData)
};
}).catch(err => {
const errorMessage = `Registry error ${err.message}`;
return {
error: errorMessage
};
});
}
module.exports = getNpmInfo;
================================================
FILE: lib/in/get-unused-packages.js
================================================
'use strict';
const depcheck = require('depcheck');
const ora = require('ora');
const _ = require('lodash');
const { rcFile } = require('rc-config-loader');
function skipUnused(currentState) {
return currentState.get('skipUnused') || // manual option to ignore this
currentState.get('global') || // global modules
currentState.get('update') || // in the process of doing an update
!currentState.get('cwdPackageJson').name; // there's no package.json
}
function loadRcFile(rcFileName) {
try {
const results = rcFile(rcFileName);
// Not Found
if (!results) {
return {};
}
return results.config;
} catch (error) {
console.error(`Error parsing rc file; skipping it; error: ${error.message}`);
return {}; // default value
}
}
function getSpecialParsers(currentState) {
const specialsInput = currentState.get('specials');
if (!specialsInput) return;
return specialsInput
.split(',')
.map((special) => depcheck.special[special])
.filter(Boolean);
}
function checkUnused(currentState) {
const spinner = ora(`Checking for unused packages. --skip-unused if you don't want this.`);
spinner.enabled = spinner.enabled && currentState.get('spinner');
spinner.start();
return new Promise(resolve => {
if (skipUnused(currentState)) {
resolve(currentState);
return;
}
const depcheckDefaults = {
ignoreDirs: [
'sandbox',
'dist',
'generated',
'.generated',
'build',
'fixtures',
'jspm_packages'
],
ignoreMatches: [
'gulp-*',
'grunt-*',
'karma-*',
'angular-*',
'babel-*',
'metalsmith-*',
'eslint-plugin-*',
'@types/*',
'grunt',
'mocha',
'ava'
],
specials: getSpecialParsers(currentState)
};
const npmCheckRc = loadRcFile('npmcheck');
const depcheckOptions = {
...depcheckDefaults,
...npmCheckRc.depcheck
};
depcheck(currentState.get('cwd'), depcheckOptions, resolve);
}).then(depCheckResults => {
spinner.stop();
const unusedDependencies = [].concat(depCheckResults.dependencies, depCheckResults.devDependencies);
currentState.set('unusedDependencies', unusedDependencies);
const cwdPackageJson = currentState.get('cwdPackageJson');
// currently missing will return devDependencies that aren't really missing
const missingFromPackageJson = _.omit(depCheckResults.missing || {},
Object.keys(cwdPackageJson.dependencies), Object.keys(cwdPackageJson.devDependencies));
currentState.set('missingFromPackageJson', missingFromPackageJson);
return currentState;
});
}
module.exports = checkUnused;
================================================
FILE: lib/in/index.js
================================================
'use strict';
const co = require('co');
const extend = require('xtend');
const ora = require('ora');
const getUnusedPackages = require('./get-unused-packages');
const createPackageSummary = require('./create-package-summary');
module.exports = function (currentState) {
return co(function *() {
yield getUnusedPackages(currentState);
const spinner = ora(`Checking npm registries for updated packages.`);
spinner.enabled = spinner.enabled && currentState.get('spinner');
spinner.start();
const cwdPackageJson = currentState.get('cwdPackageJson');
function dependencies(pkg) {
if (currentState.get('global')) {
return currentState.get('globalPackages');
}
if (currentState.get('ignoreDev')) {
return pkg.dependencies;
}
if (currentState.get('devOnly')) {
return pkg.devDependencies;
}
return extend(pkg.dependencies, pkg.devDependencies);
}
const allDependencies = dependencies(cwdPackageJson);
const allDependenciesIncludingMissing = Object.keys(extend(allDependencies, currentState.get('missingFromPackageJson')));
const arrayOfPackageInfo = yield allDependenciesIncludingMissing
.map(moduleName => createPackageSummary(moduleName, currentState))
.filter(Boolean);
currentState.set('packages', arrayOfPackageInfo);
spinner.stop();
return currentState;
});
};
================================================
FILE: lib/in/read-package-json.js
================================================
'use strict';
const extend = require('xtend');
function readPackageJson(filename) {
let pkg;
let error;
try {
pkg = require(filename);
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
error = new Error(`A package.json was not found at ${filename}`);
} else {
error = new Error(`A package.json was found at ${filename}, but it is not valid.`);
}
}
return extend({devDependencies: {}, dependencies: {}, error: error}, pkg)
}
module.exports = readPackageJson;
================================================
FILE: lib/index.js
================================================
'use strict';
const npmCheck = require('./in');
const createState = require('./state/state');
async function init(userOptions) {
return npmCheck(await createState(userOptions));
}
module.exports = init;
================================================
FILE: lib/out/emoji.js
================================================
'use strict';
const emoji = require('node-emoji');
let emojiEnabled = true;
function output(name) {
if (emojiEnabled) {
return emoji.emojify(name);
}
return '';
}
function enabled(val) {
emojiEnabled = val;
}
module.exports = output;
module.exports.enabled = enabled;
================================================
FILE: lib/out/install-packages.js
================================================
'use strict';
const chalk = require('chalk');
const execa = require('execa');
const ora = require('ora');
function install(packages, currentState) {
if (!packages.length) {
return Promise.resolve(currentState);
}
const installer = currentState.get('installer');
const color = chalk.supportsColor ? '--color=always' : null;
const isYarn = installer === 'yarn';
const installGlobal = currentState.get('global') ? (isYarn ? 'global' : '--global'): null;
const saveExact = currentState.get('saveExact') ? (isYarn ? '--exact' : '--save-exact') : null;
const installCmd = isYarn ? 'add' : 'install';
const npmArgs = [installCmd]
.concat(installGlobal)
.concat(saveExact)
.concat(packages)
.concat(color)
.filter(Boolean);
console.log('');
console.log(`$ ${chalk.green(installer)} ${chalk.green(npmArgs.join(' '))}`);
const spinner = ora(`Installing using ${chalk.green(installer)}...`);
spinner.enabled = spinner.enabled && currentState.get('spinner');
spinner.start();
return execa(installer, npmArgs, {cwd: currentState.get('cwd')}).then(output => {
spinner.stop();
console.log(output.stdout);
console.log(output.stderr);
return currentState;
}).catch(err => {
spinner.stop();
throw err;
});
}
module.exports = install;
================================================
FILE: lib/out/interactive-update.js
================================================
'use strict';
const _ = require('lodash');
const inquirer = require('inquirer');
const chalk = require('chalk');
const table = require('text-table');
const installPackages = require('./install-packages');
const emoji = require('./emoji');
const stripAnsi = require('strip-ansi');
const UI_GROUPS = [
{
title: chalk.bold.underline.green('Update package.json to match version installed.'),
filter: {mismatch: true, bump: null}
},
{
title: `${chalk.bold.underline.green('Missing.')} ${chalk.green('You probably want these.')}`,
filter: {notInstalled: true, bump: null}
},
{
title: `${chalk.bold.underline.green('Patch Update')} ${chalk.green('Backwards-compatible bug fixes.')}`,
filter: {bump: 'patch'}
},
{
title: `${chalk.yellow.underline.bold('Minor Update')} ${chalk.yellow('New backwards-compatible features.')}`,
bgColor: 'yellow',
filter: {bump: 'minor'}
},
{
title: `${chalk.red.underline.bold('Major Update')} ${chalk.red('Potentially breaking API changes. Use caution.')}`,
filter: {bump: 'major'}
},
{
title: `${chalk.magenta.underline.bold('Non-Semver')} ${chalk.magenta('Versions less than 1.0.0, caution.')}`,
filter: {bump: 'nonSemver'}
}
];
function label(pkg) {
const bumpInstalled = pkg.bump ? pkg.installed : '';
const installed = pkg.mismatch ? pkg.packageJson : bumpInstalled;
const name = chalk.yellow(pkg.moduleName);
const type = pkg.devDependency ? chalk.green(' devDep') : '';
const missing = pkg.notInstalled ? chalk.red(' missing') : '';
const homepage = pkg.homepage ? chalk.blue.underline(pkg.homepage) : '';
return [
name + type + missing,
installed,
installed && '❯',
chalk.bold(pkg.latest || ''),
pkg.latest ? homepage : pkg.regError || pkg.pkgError
];
}
function short(pkg) {
return `${pkg.moduleName}@${pkg.latest}`;
}
function choice(pkg) {
if (!pkg.mismatch && !pkg.bump && !pkg.notInstalled) {
return false;
}
return {
value: pkg,
name: label(pkg),
short: short(pkg)
};
}
function unselectable(options) {
return new inquirer.Separator(chalk.reset(options ? options.title : ' '));
}
function createChoices(packages, options) {
const filteredChoices = _.filter(packages, options.filter);
const choices = filteredChoices.map(choice)
.filter(Boolean);
const choicesAsATable = table(_.map(choices, 'name'), {
align: ['l', 'l', 'l'],
stringLength: function (str) {
return stripAnsi(str).length;
}
}).split('\n');
const choicesWithTableFormating = _.map(choices, (choice, i) => {
choice.name = choicesAsATable[i];
return choice;
});
if (choicesWithTableFormating.length) {
choices.unshift(unselectable(options));
choices.unshift(unselectable());
return choices;
}
}
function buildPackageToUpdate(moduleName, version, isYarn, saveExact) {
// handle adding ^ for yarn, npm seems to handle this if not exact
return (isYarn && !saveExact) ? moduleName + '@^' + version : moduleName + '@' + version;
}
function interactive(currentState) {
const packages = currentState.get('packages');
if (currentState.get('debug')) {
console.log('packages', packages);
}
const choicesGrouped = UI_GROUPS.map(group => createChoices(packages, group))
.filter(Boolean);
const choices = _.flatten(choicesGrouped);
if (!choices.length) {
console.log(`${emoji(':heart: ')}Your modules look ${chalk.bold('amazing')}. Keep up the great work.${emoji(' :heart:')}`);
return;
}
choices.push(unselectable());
choices.push(unselectable({title: 'Space to select. Enter to start upgrading. Control-C to cancel.'}));
const questions = [
{
name: 'packages',
message: 'Choose which packages to update.',
type: 'checkbox',
choices: choices.concat(unselectable()),
pageSize: process.stdout.rows - 2
}
];
return inquirer.prompt(questions).then(answers => {
const packagesToUpdate = answers.packages;
const isYarn = currentState.get('installer') === 'yarn';
const saveExact = currentState.get('saveExact');
if (!packagesToUpdate || !packagesToUpdate.length) {
console.log('No packages selected for update.');
return false;
}
const saveDependencies = packagesToUpdate
.filter(pkg => !pkg.devDependency)
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));
const saveDevDependencies = packagesToUpdate
.filter(pkg => pkg.devDependency)
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));
const updatedPackages = packagesToUpdate
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact)).join(', ');
if (!currentState.get('global')) {
if (saveDependencies.length) {
!isYarn && saveDependencies.push('--save');
}
if (saveDevDependencies.length) {
isYarn ? saveDevDependencies.push('--dev') : saveDevDependencies.push('--save-dev');
}
}
return installPackages(saveDependencies, currentState)
.then(currentState => installPackages(saveDevDependencies, currentState))
.then(currentState => {
console.log('');
console.log(chalk.green(`[npm-check] Update complete!`));
console.log(chalk.green('[npm-check] ' + updatedPackages));
console.log(chalk.green(`[npm-check] You should re-run your tests to make sure everything works with the updates.`));
return currentState;
});
});
}
module.exports = interactive;
================================================
FILE: lib/out/static-output.js
================================================
'use strict';
const chalk = require('chalk');
const _ = require('lodash');
const table = require('text-table');
const emoji = require('./emoji');
const stripAnsi = require('strip-ansi');
function uppercaseFirstLetter(str) {
return str[0].toUpperCase() + str.substr(1);
}
function render(pkg, currentState) {
const packageName = pkg.moduleName;
const rows = [];
const indent = ' ' + emoji(' ');
const installer = currentState.get('installer');
const isYarn = installer === 'yarn';
const args = [isYarn ? 'add' : 'install'];
if (currentState.get('global')) {
isYarn ? args.unshift('global') : args.push('--global');
}
const flags = [];
if (isYarn) {
pkg.devDependency && flags.push('--dev');
} else {
pkg.devDependency ? flags.push('--save-dev') : flags.push('--save');
}
const upgradeCommand = `${installer} ${args.join(' ')} ${packageName}@${pkg.latest} ${flags.join(' ')}`;
const upgradeMessage = `${chalk.green(upgradeCommand)} to go from ${pkg.installed} to ${pkg.latest}`;
// DYLAN: clean this up
const status = _([
pkg.notInstalled ? chalk.bgRed.white.bold(emoji(' :worried: ') + ' MISSING! ') + ' Not installed.' : '',
pkg.notInPackageJson ? chalk.bgRed.white.bold(emoji(' :worried: ') + ' PKG ERR! ') + ' Not in the package.json. ' + pkg.notInPackageJson : '',
pkg.pkgError && !pkg.notInstalled ? chalk.bgGreen.white.bold(emoji(' :worried: ') + ' PKG ERR! ') + ' ' + chalk.red(pkg.pkgError.message) : '',
pkg.bump && pkg.easyUpgrade ? [
chalk.bgGreen.white.bold(emoji(' :heart_eyes: ') + ' UPDATE! ') + ' Your local install is out of date. ' + chalk.blue.underline(pkg.homepage || ''),
indent + upgradeMessage
] : '',
pkg.bump && !pkg.easyUpgrade ? [
chalk.white.bold.bgGreen((pkg.bump === 'nonSemver' ? emoji(' :sunglasses: ') + ' new ver! '.toUpperCase() : emoji(' :sunglasses: ') + ' ' + pkg.bump.toUpperCase() + ' UP ')) + ' ' + uppercaseFirstLetter(pkg.bump) + ' update available. ' + chalk.blue.underline(pkg.homepage || ''),
indent + upgradeMessage
] : '',
pkg.unused ? [
chalk.black.bold.bgWhite(emoji(' :confused: ') + ' NOTUSED? ') + ` ${chalk.yellow(`Still using ${packageName}?`)}`,
indent + `Depcheck did not find code similar to ${chalk.green(`require('${packageName}')`)} or ${chalk.green(`import from '${packageName}'`)}.`,
indent + `Check your code before removing as depcheck isn't able to foresee all ways dependencies can be used.`,
indent + `Use rc file options to remove unused check, but still monitor for outdated version:`,
indent + ` .npmcheckrc {"depcheck": {"ignoreMatches": ["${packageName}"]}}`,
indent + `Use ${chalk.green('--skip-unused')} to skip this check.`,
indent + `To remove this package: ${chalk.green(
isYarn
? `yarn remove ${packageName} ${pkg.devDependency ? '--dev' : ''}`
: `npm uninstall ${packageName} --save${pkg.devDependency ? '-dev' : ''}`
)}`
] : '',
pkg.mismatch && !pkg.bump ? chalk.bgRed.yellow.bold(emoji(' :interrobang: ') + ' MISMATCH ') + ' Installed version does not match package.json. ' + pkg.installed + ' ≠ ' + pkg.packageJson : '',
pkg.regError ? chalk.bgRed.white.bold(emoji(' :no_entry: ') + ' NPM ERR! ') + ' ' + chalk.red(pkg.regError) : ''
])
.flatten()
.compact()
.valueOf();
if (!status.length) {
return false;
}
rows.push(
[
chalk.yellow(packageName),
status.shift()
]);
while (status.length) {
rows.push([
' ',
status.shift()
]);
}
rows.push(
[
' '
]);
return rows;
}
function outputConsole(currentState) {
const packages = currentState.get('packages');
const rows = packages.reduce((acc, pkg) => {
return acc.concat(render(pkg, currentState));
}, [])
.filter(Boolean);
if (rows.length) {
const renderedTable = table(rows, {
stringLength: s => stripAnsi(s).length
});
console.log('');
console.log(renderedTable);
console.log(`Use ${chalk.green(`npm-check -${currentState.get('global') ? 'g' : ''}u`)} for interactive update.`);
process.exitCode = 1;
} else {
console.log(`${emoji(':heart: ')}Your modules look ${chalk.bold('amazing')}. Keep up the great work.${emoji(' :heart:')}`);
process.exitCode = 0;
}
}
module.exports = outputConsole;
================================================
FILE: lib/out/update-all.js
================================================
'use strict';
const chalk = require('chalk');
const installPackages = require('./install-packages');
const emoji = require('./emoji');
function buildPackageToUpdate(moduleName, version, isYarn, saveExact) {
// handle adding ^ for yarn, npm seems to handle this if not exact
return (isYarn && !saveExact) ? moduleName + '@^' + version : moduleName + '@' + version;
}
function updateAll(currentState) {
const packages = currentState.get('packages');
if (currentState.get('debug')) {
console.log('packages', packages);
}
const packagesToUpdate = packages.filter(packageEntry => packageEntry.mismatch || packageEntry.notInstalled || packageEntry.bump );
if (!packagesToUpdate.length) {
console.log(`${emoji(':heart: ')}Your modules look ${chalk.bold('amazing')}. Keep up the great work.${emoji(' :heart:')}`);
return;
}
const isYarn = currentState.get('installer') === 'yarn';
const saveExact = currentState.get('saveExact');
const saveDependencies = packagesToUpdate
.filter(pkg => !pkg.devDependency)
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));
const saveDevDependencies = packagesToUpdate
.filter(pkg => pkg.devDependency)
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));
const updatedPackages = packagesToUpdate
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact)).join(', ');
if (!currentState.get('global')) {
if (saveDependencies.length) {
!isYarn && saveDependencies.push('--save');
}
if (saveDevDependencies.length) {
isYarn
? saveDevDependencies.push('--dev')
: saveDevDependencies.push('--save-dev');
}
}
return installPackages(saveDependencies, currentState)
.then(currentState => installPackages(saveDevDependencies, currentState))
.then(currentState => {
console.log('');
console.log(chalk.green(`[npm-check] Update complete!`));
console.log(chalk.green('[npm-check] ' + updatedPackages));
console.log(chalk.green(`[npm-check] You should re-run your tests to make sure everything works with the updates.`));
return currentState;
});
}
module.exports = updateAll;
================================================
FILE: lib/state/debug.js
================================================
'use strict';
const chalk = require('chalk');
function debug() {
console.log(chalk.green('[npm-check] debug'));
console.log.apply(console, arguments);
console.log(`${chalk.green('===============================')}`);
}
module.exports = debug;
================================================
FILE: lib/state/init.js
================================================
'use strict';
const _ = require('lodash');
const path = require('path');
const globalModulesPath = require('global-modules');
const readPackageJson = require('../in/read-package-json');
const globalPackages = require('../in/get-installed-packages');
const emoji = require('../out/emoji');
const fs = require('fs');
const chalk = require('chalk');
function init(currentState, userOptions) {
return new Promise((resolve, reject) => {
_.each(userOptions, (value, key) => currentState.set(key, value));
if (currentState.get('global')) {
let modulesPath = globalModulesPath;
if (process.env.NODE_PATH) {
if (process.env.NODE_PATH.indexOf(path.delimiter) !== -1) {
modulesPath = process.env.NODE_PATH.split(path.delimiter)[0];
console.log(chalk.yellow('warning: Using the first of multiple paths specified in NODE_PATH'));
} else {
modulesPath = process.env.NODE_PATH;
}
}
if (!fs.existsSync(modulesPath)) {
throw new Error('Path "' + modulesPath + '" does not exist. Please check the NODE_PATH environment variable.');
}
console.log(chalk.green('The global path you are searching is: ' + modulesPath));
currentState.set('cwd', globalModulesPath);
currentState.set('globalPackages', globalPackages(modulesPath));
} else {
const cwd = path.resolve(currentState.get('cwd'));
const pkg = readPackageJson(path.join(cwd, 'package.json'));
currentState.set('cwdPackageJson', pkg);
currentState.set('cwd', cwd);
}
emoji.enabled(currentState.get('emoji'));
if (currentState.get('cwdPackageJson').error) {
return reject(currentState.get('cwdPackageJson').error);
}
return resolve(currentState);
});
}
module.exports = init;
================================================
FILE: lib/state/state.js
================================================
'use strict';
const extend = require('xtend');
const init = require('./init');
const debug = require('./debug');
const defaultOptions = {
update: false,
updateAll: false,
global: false,
cwd: process.cwd(),
skipUnused: false,
ignoreDev: false,
devOnly: false,
forceColor: false,
saveExact: false,
specials: '',
debug: false,
emoji: true,
spinner: false,
installer: 'npm',
ignore: [],
globalPackages: {},
cwdPackageJson: {devDependencies: {}, dependencies: {}},
packages: false,
unusedDependencies: false,
missingFromPackageJson: {}
};
function state(userOptions) {
const currentStateObject = extend(defaultOptions);
function get(key) {
if (!currentStateObject.hasOwnProperty(key)) {
throw new Error(`Can't get unknown option "${key}".`);
}
return currentStateObject[key];
}
function set(key, value) {
if (get('debug')) {
debug('set key', key, 'to value', value);
}
if (currentStateObject.hasOwnProperty(key)) {
currentStateObject[key] = value;
} else {
throw new Error(`unknown option "${key}" setting to "${JSON.stringify(value, false, 4)}".`);
}
}
function inspectIfDebugMode() {
if (get('debug')) {
inspect();
}
}
function inspect() {
debug('current state', all());
}
function all() {
return currentStateObject;
}
const currentState = {
get: get,
set: set,
all,
inspectIfDebugMode
};
return init(currentState, userOptions);
}
module.exports = state;
================================================
FILE: license
================================================
The MIT License (MIT)
Copyright (c) Dylan Greene <dylang@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: package.json
================================================
{
"name": "npm-check",
"version": "6.0.1",
"description": "Check for outdated, incorrect, and unused dependencies.",
"main": "lib",
"engines": {
"node": ">=24.14.0"
},
"types": "./index.d.ts",
"typings": "./index.d.ts",
"scripts": {
"lint": "xo ./lib/*.js",
"test": "npm run lint && ./bin/cli.js || echo Exit Status: $?.",
"transpile": "babel lib --out-dir lib-es5",
"watch": "babel lib --out-dir lib-es5 --watch",
"prepublish": "npm run transpile"
},
"xo": {
"space": 4,
"rules": {
"no-warning-comments": [
0
],
"global-require": [
0
]
}
},
"bin": {
"npm-check": "bin/cli.js"
},
"repository": {
"type": "git",
"url": "https://github.com/dylang/npm-check.git"
},
"keywords": [
"npm",
"outdated",
"dependencies",
"unused",
"changelog",
"check",
"updates",
"api",
"interactive",
"cli",
"safe",
"updating",
"updater",
"installer",
"devDependencies"
],
"author": {
"name": "Dylan Greene",
"email": "dylang@gmail.com"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/dylang/npm-check/issues"
},
"homepage": "https://github.com/dylang/npm-check",
"files": [
"bin",
"lib",
"lib-es5"
],
"dependencies": {
"callsite-record": "^4.1.5",
"chalk": "^5.6.2",
"co": "^4.6.0",
"depcheck": "^1.4.7",
"execa": "^9.6.1",
"giturl": "^2.0.0",
"global-modules": "^2.0.0",
"globby": "^16.1.1",
"inquirer": "^13.3.2",
"is-ci": "^4.1.0",
"lodash": "^4.17.23",
"meow": "^14.1.0",
"minimatch": "^10.2.4",
"node-emoji": "^2.2.0",
"ora": "^9.3.0",
"package-json": "^10.0.1",
"path-exists": "^5.0.0",
"pkg-dir": "^9.0.0",
"preferred-pm": "^5.0.0",
"rc-config-loader": "^4.1.4",
"semver": "^7.7.4",
"semver-diff": "^5.0.0",
"strip-ansi": "^7.2.0",
"text-table": "^0.2.0",
"throat": "^6.0.2",
"update-notifier": "^7.3.1",
"xtend": "^4.0.2"
},
"devDependencies": {
"babel-runtime": "^6.26.0",
"babel-cli": "^6.26.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"xo": "^0.37.1"
}
}
================================================
FILE: renovate.json
================================================
{
"$schema": "https://json.schemastore.org/renovate",
"extends": [
"config:base",
":rebaseStalePrs",
":semanticCommits",
":automergeAll",
":maintainLockFilesWeekly",
":prHourlyLimitNone"
],
"timezone": "America/New_York",
"rangeStrategy": "bump",
"schedule": [ "every weekend"],
"updateNotScheduled": false,
"lockFileMaintenance": {
"enabled": true,
"schedule": [ "every weekend" ]
}
}
gitextract_76r69cho/ ├── .babelrc ├── .editorconfig ├── .gitignore ├── .travis.yml ├── .vscode/ │ └── launch.json ├── README.md ├── appveyor.yml ├── bin/ │ └── cli.js ├── index.d.ts ├── lib/ │ ├── cli.js │ ├── in/ │ │ ├── best-guess-homepage.js │ │ ├── create-package-summary.js │ │ ├── find-module-path.js │ │ ├── get-installed-packages.js │ │ ├── get-latest-from-registry.js │ │ ├── get-unused-packages.js │ │ ├── index.js │ │ └── read-package-json.js │ ├── index.js │ ├── out/ │ │ ├── emoji.js │ │ ├── install-packages.js │ │ ├── interactive-update.js │ │ ├── static-output.js │ │ └── update-all.js │ └── state/ │ ├── debug.js │ ├── init.js │ └── state.js ├── license ├── package.json └── renovate.json
SYMBOL INDEX (37 symbols across 18 files)
FILE: index.d.ts
type INpmCheckOptions (line 2) | interface INpmCheckOptions {
type INpmCheckGetSetValues (line 13) | type INpmCheckGetSetValues = "packages" | "debug" | "global" | "cwd" | "...
type INpmVersionBumpType (line 15) | type INpmVersionBumpType = "patch" | "minor" | "major" | "prerelease" | ...
type INpmCheckCurrentState (line 17) | interface INpmCheckCurrentState {
type INpmCheckPackage (line 22) | interface INpmCheckPackage {
FILE: lib/cli.js
constant SUPPORTED_INSTALLERS (line 159) | const SUPPORTED_INSTALLERS = new Set(['npm', 'pnpm', 'ied', 'yarn']);
function detectPreferredInstaller (line 161) | async function detectPreferredInstaller(cwd) {
FILE: lib/in/best-guess-homepage.js
function bestGuessHomepage (line 5) | function bestGuessHomepage(data) {
FILE: lib/in/create-package-summary.js
function createPackageSummary (line 13) | function createPackageSummary(moduleName, currentState) {
FILE: lib/in/find-module-path.js
function findModulePath (line 11) | function findModulePath(moduleName, currentState) {
FILE: lib/in/get-latest-from-registry.js
function getNpmInfo (line 10) | function getNpmInfo(packageName) {
FILE: lib/in/get-unused-packages.js
function skipUnused (line 8) | function skipUnused(currentState) {
function loadRcFile (line 15) | function loadRcFile(rcFileName) {
function getSpecialParsers (line 29) | function getSpecialParsers(currentState) {
function checkUnused (line 38) | function checkUnused(currentState) {
FILE: lib/in/index.js
function dependencies (line 18) | function dependencies(pkg) {
FILE: lib/in/read-package-json.js
function readPackageJson (line 5) | function readPackageJson(filename) {
FILE: lib/index.js
function init (line 6) | async function init(userOptions) {
FILE: lib/out/emoji.js
function output (line 7) | function output(name) {
function enabled (line 15) | function enabled(val) {
FILE: lib/out/install-packages.js
function install (line 7) | function install(packages, currentState) {
FILE: lib/out/interactive-update.js
constant UI_GROUPS (line 11) | const UI_GROUPS = [
function label (line 39) | function label(pkg) {
function short (line 55) | function short(pkg) {
function choice (line 59) | function choice(pkg) {
function unselectable (line 71) | function unselectable(options) {
function createChoices (line 75) | function createChoices(packages, options) {
function buildPackageToUpdate (line 100) | function buildPackageToUpdate(moduleName, version, isYarn, saveExact) {
function interactive (line 105) | function interactive(currentState) {
FILE: lib/out/static-output.js
function uppercaseFirstLetter (line 9) | function uppercaseFirstLetter(str) {
function render (line 13) | function render(pkg, currentState) {
function outputConsole (line 94) | function outputConsole(currentState) {
FILE: lib/out/update-all.js
function buildPackageToUpdate (line 7) | function buildPackageToUpdate(moduleName, version, isYarn, saveExact) {
function updateAll (line 12) | function updateAll(currentState) {
FILE: lib/state/debug.js
function debug (line 4) | function debug() {
FILE: lib/state/init.js
function init (line 11) | function init(currentState, userOptions) {
FILE: lib/state/state.js
function state (line 32) | function state(userOptions) {
Condensed preview — 30 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (63K chars).
[
{
"path": ".babelrc",
"chars": 116,
"preview": "{\n \"presets\": [\n \"es2015\"\n ],\n \"plugins\": [\n \"transform-runtime\",\n \"transform-object-rest-spread\"\n ]\n}\n"
},
{
"path": ".editorconfig",
"chars": 446,
"preview": "# Get the plugin for your editor and your\n# tab settings will be set automatically.\n# http://EditorConfig.org\n\n# top-mos"
},
{
"path": ".gitignore",
"chars": 40,
"preview": "/.idea/\n/node_modules/\n/*.log\n/lib-es5/\n"
},
{
"path": ".travis.yml",
"chars": 89,
"preview": "sudo: false\n\nlanguage: node_js\n\nos:\n - linux\n - osx\n\nnode_js:\n - 12.22.12\n - 10.24.1\n"
},
{
"path": ".vscode/launch.json",
"chars": 405,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n //"
},
{
"path": "README.md",
"chars": 14347,
"preview": "npm-check\n=========\n[](https://travis-ci.org/dy"
},
{
"path": "appveyor.yml",
"chars": 394,
"preview": "environment:\n matrix:\n - nodejs_version: 12\n - nodejs_version: 10\n\ninstall:\n - ps: Install-Product node $env:nodejs_"
},
{
"path": "bin/cli.js",
"chars": 182,
"preview": "#!/usr/bin/env node\n\nvar isEs2015;\ntry {\n isEs2015 = new Function('() => {}');\n} catch (e) {\n isEs2015 = false;\n}\n"
},
{
"path": "index.d.ts",
"chars": 2265,
"preview": "declare module NpmCheck { \n interface INpmCheckOptions {\n global?: boolean;\n update?: boolean;\n skipUnused?: b"
},
{
"path": "lib/cli.js",
"chars": 5054,
"preview": "#!/usr/bin/env node\n'use strict';\n\nconst meow = require('meow');\nconst updateNotifier = require('update-notifier');\ncons"
},
{
"path": "lib/in/best-guess-homepage.js",
"chars": 553,
"preview": "'use strict';\n\nconst gitUrl = require('giturl');\n\nfunction bestGuessHomepage(data) {\n if (!data) {\n return fal"
},
{
"path": "lib/in/create-package-summary.js",
"chars": 4407,
"preview": "'use strict';\n\nconst readPackageJson = require('./read-package-json');\nconst getLatestFromRegistry = require('./get-late"
},
{
"path": "lib/in/find-module-path.js",
"chars": 1225,
"preview": "'use strict';\n\nconst Module = require('module');\nconst path = require('path');\nconst pathExists = require('path-exists')"
},
{
"path": "lib/in/get-installed-packages.js",
"chars": 571,
"preview": "'use strict';\nconst _ = require('lodash');\nconst globby = require('globby');\nconst readPackageJson = require('./read-pac"
},
{
"path": "lib/in/get-latest-from-registry.js",
"chars": 1367,
"preview": "'use strict';\n\nconst _ = require('lodash');\nconst bestGuessHomepage = require('./best-guess-homepage');\nconst semver = r"
},
{
"path": "lib/in/get-unused-packages.js",
"chars": 3132,
"preview": "'use strict';\n\nconst depcheck = require('depcheck');\nconst ora = require('ora');\nconst _ = require('lodash');\nconst { rc"
},
{
"path": "lib/in/index.js",
"chars": 1538,
"preview": "'use strict';\nconst co = require('co');\nconst extend = require('xtend');\nconst ora = require('ora');\nconst getUnusedPack"
},
{
"path": "lib/in/read-package-json.js",
"chars": 542,
"preview": "'use strict';\n\nconst extend = require('xtend');\n\nfunction readPackageJson(filename) {\n let pkg;\n let error;\n tr"
},
{
"path": "lib/index.js",
"chars": 210,
"preview": "'use strict';\n\nconst npmCheck = require('./in');\nconst createState = require('./state/state');\n\nasync function init(user"
},
{
"path": "lib/out/emoji.js",
"chars": 298,
"preview": "'use strict';\n\nconst emoji = require('node-emoji');\n\nlet emojiEnabled = true;\n\nfunction output(name) {\n if (emojiEnab"
},
{
"path": "lib/out/install-packages.js",
"chars": 1391,
"preview": "'use strict';\n\nconst chalk = require('chalk');\nconst execa = require('execa');\nconst ora = require('ora');\n\nfunction ins"
},
{
"path": "lib/out/interactive-update.js",
"chars": 6030,
"preview": "'use strict';\n\nconst _ = require('lodash');\nconst inquirer = require('inquirer');\nconst chalk = require('chalk');\nconst "
},
{
"path": "lib/out/static-output.js",
"chars": 4709,
"preview": "'use strict';\n\nconst chalk = require('chalk');\nconst _ = require('lodash');\nconst table = require('text-table');\nconst e"
},
{
"path": "lib/out/update-all.js",
"chars": 2387,
"preview": "'use strict';\n\nconst chalk = require('chalk');\nconst installPackages = require('./install-packages');\nconst emoji = requ"
},
{
"path": "lib/state/debug.js",
"chars": 257,
"preview": "'use strict';\nconst chalk = require('chalk');\n\nfunction debug() {\n console.log(chalk.green('[npm-check] debug'));\n "
},
{
"path": "lib/state/init.js",
"chars": 1971,
"preview": "'use strict';\nconst _ = require('lodash');\nconst path = require('path');\nconst globalModulesPath = require('global-modul"
},
{
"path": "lib/state/state.js",
"chars": 1689,
"preview": "'use strict';\nconst extend = require('xtend');\nconst init = require('./init');\nconst debug = require('./debug');\n\nconst "
},
{
"path": "license",
"chars": 1093,
"preview": "The MIT License (MIT)\n\nCopyright (c) Dylan Greene <dylang@gmail.com>\n\nPermission is hereby granted, free of charge, to a"
},
{
"path": "package.json",
"chars": 2312,
"preview": "{\n \"name\": \"npm-check\",\n \"version\": \"6.0.1\",\n \"description\": \"Check for outdated, incorrect, and unused dependencies."
},
{
"path": "renovate.json",
"chars": 436,
"preview": "{\n \"$schema\": \"https://json.schemastore.org/renovate\",\n \"extends\": [\n \"config:base\",\n \":rebaseStalePrs\",\n \":s"
}
]
About this extraction
This page contains the full source code of the dylang/npm-check GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 30 files (58.1 KB), approximately 14.7k tokens, and a symbol index with 37 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.