Skip to content

Commit

Permalink
Latest packages; added basic yarn support; added rc file depcheck api…
Browse files Browse the repository at this point in the history
… support (#397)

* updated to latest package versions (node 10+);
added support for rcfile;
added babel support for spread operator;
added yarn support;

* Update lib/in/get-unused-packages.js

switch to const

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>

* Update lib/cli.js

switched to set

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>

* Update lib/index.js

streamline

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>

* Update package.json

updated node version

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>

* PR feedback - clean up

Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>
  • Loading branch information
dkhunt27 and LinusU committed Jul 16, 2022
1 parent f92f449 commit 3c8798d
Show file tree
Hide file tree
Showing 14 changed files with 6,440 additions and 3,481 deletions.
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://docs.npmjs.com/cli/v7/commands/npm-outdated) - 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

0 comments on commit 3c8798d

Please sign in to comment.