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

Implement global package upgrade #70

Merged
merged 16 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ If you want to check only a group of deps use these options:
-o, --optional Check only "optionalDependencies"
```

Alternatively, you can use the `-g` (`--global`) flag to upgrade your global packages. **Note** that this flag is mutually exclusive and `npm-upgrade` will only recognise the global flag if supplied with others. Also **Note** that this option will automatically attempt to upgrade your global packages using `npm install -g <package>@<new-version>`.

#### Ignoring module
Sometimes you just want to ignore newer versions of some dependency for some reason. For example, you use `jquery v2` because of the old IE support and don't want `npm-upgrade` to suggest you updating it to `v3`. Or you use `some-funky-module@6.6.5` and know that the new version `6.6.6` contains a bug that breaks your app.

Expand Down
26 changes: 12 additions & 14 deletions src/commands/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {colorizeDiff} from 'npm-check-updates/lib/version-util';

import catchAsyncError from '../catchAsyncError';
import {makeFilterFunction} from '../filterUtils';
import {DEPS_GROUPS, createGlobalPackageJson, loadPackageJson, setModuleVersion, getModuleInfo, getModuleHomepage} from '../packageUtils';
import {DEPS_GROUPS, loadGlobalPackages, loadPackageJson, setModuleVersion,
getModuleInfo, getModuleHomepage} from '../packageUtils';
import {fetchRemoteDb, findModuleChangelogUrl} from '../changelogUtils';
import {createSimpleTable} from '../cliTable';
import {strong, success, attention} from '../cliStyles';
Expand Down Expand Up @@ -56,18 +57,15 @@ export const handler = catchAsyncError(async opts => {
if (_.every(DEPS_GROUPS, ({name}) => !opts[name])) {
_.each(DEPS_GROUPS, ({name}) => (opts[name] = true));
opts.global = false;
}

// Make global flag mutually exclusive with other flags
else if (opts.global) {
for (let i = 0; i < DEPS_GROUPS.length; i++)
opts[DEPS_GROUPS[i].name] = false;
} else if (opts.global) {
// Make global flag mutually exclusive with other flags
for (let i = 0; i < DEPS_GROUPS.length; i++) {_.each(DEPS_GROUPS, ({name}) => { opts[name] = false })}
medallyon marked this conversation as resolved.
Show resolved Hide resolved
opts.global = true;
}

// Loading `package.json` from the current directory
const {path: packageFile, content: packageJson, source: packageSource} = opts.global ?
createGlobalPackageJson() : loadPackageJson();
loadGlobalPackages() : loadPackageJson();

// Fetching remote changelogs db in background
fetchRemoteDb();
Expand All @@ -78,7 +76,8 @@ export const handler = catchAsyncError(async opts => {
const filteredWith = filter ? `filtered with ${strong(filter)} ` : '';

console.log(
`Checking for outdated ${depsGroupsToCheckStr}dependencies ${filteredWith}${opts.global ? '' : (`for "${strong(packageFile)}"`)}...`
`Checking for outdated ${depsGroupsToCheckStr}dependencies ${filteredWith}${opts.global ? '' :
(`for "${strong(packageFile)}"`)}...`
);

const ncuDepGroups = DEPS_GROUPS
Expand Down Expand Up @@ -160,7 +159,8 @@ export const handler = catchAsyncError(async opts => {

const answer = await askUser({
type: 'list',
message: `${changelogUrl === undefined ? 'U' : 'So, u'}pdate "${name}" ${opts.global ? 'globally' : 'in package.json'} from ${from} to ${colorizeDiff(from, to)}?`,
message: `${changelogUrl === undefined ? 'U' : 'So, u'}pdate "${name}" ${opts.global ? 'globally' :
'in package.json'} from ${from} to ${colorizeDiff(from, to)}?`,
choices: _.compact([
{name: 'Yes', value: true},
{name: 'No', value: false},
Expand Down Expand Up @@ -253,14 +253,12 @@ export const handler = catchAsyncError(async opts => {
'\n'
);

if (opts.global)
{
if (opts.global) {
const shouldUpdateGlobalPackages = await askUser(
{type: 'confirm', message: 'Update global modules?', default: true}
);

if (!shouldUpdateGlobalPackages)
return;
if (!shouldUpdateGlobalPackages) {return}

console.log(`Automatically upgrading ${updatedModules.length} module${updatedModules.length !== 1 ? 's' : ''}...`);
return shell.exec(`npm install --global ${updatedModules.map(({name, to}) => `${name}@${to}`).join(' ')}`);
Expand Down
59 changes: 12 additions & 47 deletions src/packageUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {resolve} from 'path';
import {readFileSync, readdirSync, statSync} from 'fs';
import {readFileSync} from 'fs';
import libnpmconfig from 'libnpmconfig';
import pacote from 'pacote';
import shell from 'shelljs';
Expand Down Expand Up @@ -32,56 +32,21 @@ const getNpmConfig = _.memoize(() => {
return config;
});

export function createGlobalPackageJson() {
// retrieve the global package install path
const res = shell.exec('npm root -g', {silent: true});
if (res.code !== 0)
throw new Error(`Could not determine npm's root path: ${res.stderr}`);

const globalPath = res.stdout?.replace('\n', '');
const pkg = { dependencies: {} };

function getPackageVersion(path)
{
try {
const packageSource = readFileSync(path, 'utf-8');
const packageJson = JSON.parse(packageSource);
if (packageJson.name && packageJson.version)
pkg.dependencies[packageJson.name] = packageJson.version;
} catch (err) {
// package.json doesn't exist for this global module
// or package.json couldn't be parsed
}
}
export function loadGlobalPackages() {
const res = shell.exec('npm ls -g --depth 0 --json', {silent: true});
if (res.code !== 0) {throw new Error(`Could not determine global packages: ${res.stderr}`)}

try {
const modules = readdirSync(globalPath);
for (const dir of modules)
{
const dirPath = resolve(globalPath, dir);
if (!statSync(dirPath).isDirectory())
continue;

if (dir.startsWith('@'))
{
const subModules = readdirSync(dirPath);
for (const subDir of subModules)
{
if (!statSync(resolve(dirPath, subDir)).isDirectory())
continue;

getPackageVersion(resolve(dirPath, subDir, 'package.json'));
}
}

else
getPackageVersion(resolve(dirPath, 'package.json'));
}
const {dependencies} = JSON.parse(res);
const content = {dependencies};

for (const [pkg, {version}] of Object.entries(dependencies)) {content.dependencies[pkg] = version}

return {content};
} catch (err) {
console.error(err);
console.error(`Error parsing global packages: ${err.message}`);
process.exit(1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decide to use process.exit here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to include it to mimic the loadPackageJson method as closely as possible, as it also calls process.exit on attempting to parse the packageJson.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any comment?

Copy link
Contributor Author

@medallyon medallyon Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry? I commented on Nov 30. Is it not visible to you?

I decided to include it to mimic the loadPackageJson method as closely as possible, as it also calls process.exit on attempting to parse the packageJson.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@medallyon any comment about this change?

}

return {content: pkg};
}

export function loadPackageJson() {
Expand Down