Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuation of @dkhunt27's #397 PR #401

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"es2015"
],
"plugins": [
"transform-runtime"
"transform-runtime",
"transform-object-rest-spread"
]
}
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ os:
node_js:
- 12
- 10
- 8
- 6
- 4
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// 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"]
}
]
}
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ npm-check
* Works with `npm@2` and `npm@3`, as well as newer alternative installers like `ied` and `pnpm`.

### Requirements
* Node >= 0.11.
* Node >= 10.9.0

### On the command line

Expand Down Expand Up @@ -267,6 +267,18 @@ Each item in the array will look like the following:

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://www.npmjs.com/doc/cli/npm-outdated.html) - awkward output, requires --depth=0 to be grokable.
Expand Down
6 changes: 2 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
environment:
matrix:
- nodejs_version: 7
- nodejs_version: 6
- nodejs_version: 4
- nodejs_version: 12
- nodejs_version: 10

install:
- ps: Install-Product node $env:nodejs_version
- npm i -g npm@3
- npm install
- set CI=true

Expand Down
112 changes: 67 additions & 45 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const detectPreferredPM = require('preferred-pm');

updateNotifier({pkg}).notify();

const cli = meow({
help: `
/* eslint-disable indent */
const cli = meow(`
Usage
$ npm-check <path> <options>

Expand All @@ -42,43 +42,65 @@ const cli = meow({
$ 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.
`},
`,
{
alias: {
u: 'update',
y: 'update-all',
g: 'global',
s: 'skip-unused',
p: 'production',
d: 'dev-only',
E: 'save-exact',
i: 'ignore'
},
default: {
dir: pkgDir.sync() || process.cwd(),
emoji: !isCI,
spinner: !isCI
},
boolean: [
'update',
'update-all',
'global',
'skip-unused',
'production',
'dev-only',
'save-exact',
'color',
'emoji',
'spinner'
],
string: [
'ignore',
'specials'
]
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] || cli.flags.dir,
cwd: cli.input[0] || pkgDir.sync() || process.cwd(),
update: cli.flags.update,
updateAll: cli.flags.updateAll,
global: cli.flags.global,
Expand Down Expand Up @@ -115,28 +137,28 @@ Promise.resolve()
if (options.updateAll) {
return updateAll(currentState);
}

if (options.update) {
return interactiveUpdate(currentState);
}

return staticOutput(currentState);
})
.catch(err => {
console.log(err.message);
.catch(error => {
console.log(error.message);

if (options.debug) {
console.log(createCallsiteRecord(err).renderSync());
console.log(createCallsiteRecord(error).renderSync());
} else {
console.log('For more detail, add `--debug` to the command');
}

process.exit(1);
});

const SUPPORTED_INSTALLERS = ['npm', 'pnpm', 'ied'];
const SUPPORTED_INSTALLERS = new Set(['npm', 'pnpm', 'ied', 'yarn']);

function detectPreferredInstaller(cwd) {
return detectPreferredPM(cwd)
.then(preferredPM => {
return preferredPM && SUPPORTED_INSTALLERS.indexOf(preferredPM.name) !== -1 ?
preferredPM.name : 'npm';
});
async function detectPreferredInstaller(cwd) {
const preferredPM = await detectPreferredPM(cwd);
return preferredPM && SUPPORTED_INSTALLERS.has(preferredPM.name) ? preferredPM.name : 'npm';
}
26 changes: 24 additions & 2 deletions lib/in/get-unused-packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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
Expand All @@ -11,6 +12,20 @@ function skipUnused(currentState) {
!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;
Expand All @@ -31,7 +46,7 @@ function checkUnused(currentState) {
return;
}

const depCheckOptions = {
const depcheckDefaults = {
ignoreDirs: [
'sandbox',
'dist',
Expand All @@ -57,7 +72,14 @@ function checkUnused(currentState) {
specials: getSpecialParsers(currentState)
};

depcheck(currentState.get('cwd'), depCheckOptions, resolve);
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);
Expand Down
5 changes: 2 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
const npmCheck = require('./in');
const createState = require('./state/state');

function init(userOptions) {
return createState(userOptions)
.then(currentState => npmCheck(currentState));
async function init(userOptions) {
return npmCheck(await createState(userOptions));
}

module.exports = init;
11 changes: 8 additions & 3 deletions lib/out/install-packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ function install(packages, currentState) {
}

const installer = currentState.get('installer');
const installGlobal = currentState.get('global') ? '--global' : null;
const saveExact = currentState.get('saveExact') ? '--save-exact' : null;
const color = chalk.supportsColor ? '--color=always' : null;

const npmArgs = ['install']
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)
Expand Down
22 changes: 15 additions & 7 deletions lib/out/interactive-update.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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 = [
{
Expand Down Expand Up @@ -80,7 +81,7 @@ function createChoices(packages, options) {
const choicesAsATable = table(_.map(choices, 'name'), {
align: ['l', 'l', 'l'],
stringLength: function (str) {
return chalk.stripColor(str).length;
return stripAnsi(str).length;
}
}).split('\n');

Expand All @@ -96,6 +97,11 @@ function createChoices(packages, options) {
}
}

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');

Expand Down Expand Up @@ -126,8 +132,10 @@ function interactive(currentState) {
}
];

return new Promise(resolve => inquirer.prompt(questions, resolve)).then(answers => {
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.');
Expand All @@ -136,22 +144,22 @@ function interactive(currentState) {

const saveDependencies = packagesToUpdate
.filter(pkg => !pkg.devDependency)
.map(pkg => pkg.moduleName + '@' + pkg.latest);
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));

const saveDevDependencies = packagesToUpdate
.filter(pkg => pkg.devDependency)
.map(pkg => pkg.moduleName + '@' + pkg.latest);
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact));

const updatedPackages = packagesToUpdate
.map(pkg => pkg.moduleName + '@' + pkg.latest).join(', ');
.map(pkg => buildPackageToUpdate(pkg.moduleName, pkg.latest, isYarn, saveExact)).join(', ');

if (!currentState.get('global')) {
if (saveDependencies.length) {
saveDependencies.unshift('--save');
!isYarn && saveDependencies.push('--save');
}

if (saveDevDependencies.length) {
saveDevDependencies.unshift('--save-dev');
isYarn ? saveDevDependencies.push('--dev') : saveDevDependencies.push('--save-dev');
}
}

Expand Down
Loading