Skip to content

Commit

Permalink
1.0.0 rm reset cmd + prefer snake_case
Browse files Browse the repository at this point in the history
  • Loading branch information
edwmurph committed Nov 5, 2022
1 parent a070996 commit 5c6dc98
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 157 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Features:
# Usage

```
Usage: npx upgrade-deps [options] [command]
Usage: npx upgrade-deps [options]
CLI for automating upgrading package.json dependencies. Semver prefixes will be stripped in favor of using exact versions.
Expand All @@ -23,9 +23,6 @@ Options:
-b, --breaking include breaking/major version upgrades
-d, --dry-run just print which packages are out of date
-h, --help display help for command
Commands:
reset does a fresh install of all dependencies
```

## npx
Expand Down
19 changes: 2 additions & 17 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

const { program } = require('commander');
const { version } = require('../package.json');
const upgradeDeps = require('../lib/upgrade-deps');
const reset = require('../lib/reset');
const upgrade_deps = require('../lib/upgrade-deps');

program
.name('npx upgrade-deps')
Expand All @@ -16,20 +15,6 @@ program
'CLI for automating upgrading package.json dependencies.',
'Semver prefixes will be stripped in favor of using exact versions.'
].join(' ') )
.action( upgradeDeps );

program
.command('reset')
.description('does a fresh install of all dependencies')
.addHelpText( 'after', `
reset command will:
- switch to the node version specified in local .nvmrc
- build a manual 'npm install ...' string via dependencies from local package.json
- install the npm deps
dependencies are installed individually rather than via 'npm install' as a
workaround to 'npm install' sometimes crashing.
` )
.action( reset );
.action( upgrade_deps );

program.parse( process.argv );
71 changes: 0 additions & 71 deletions lib/reset.js

This file was deleted.

122 changes: 62 additions & 60 deletions lib/upgrade-deps.js
Original file line number Diff line number Diff line change
@@ -1,142 +1,144 @@
const fs = require('fs');
const { promisify } = require('util');
const path = require('path');
const execAsync = require('./util/exec-async');
const exec_async = require('./util/exec-async');

const storage = '~/.upgrade-deps';

const writeFileAsync = promisify( fs.writeFile );
const semverRegexStr = '[0-9]+\\.[0-9]+\\.[0-9]+';
const semverRegex = new RegExp( semverRegexStr );
const gitSemverRegex = new RegExp( `^.+#${ semverRegexStr }$` );
const write_file_async = promisify( fs.writeFile );
const semver_regex_str = '[0-9]+\\.[0-9]+\\.[0-9]+';
const semver_regex = new RegExp( semver_regex_str );
const git_semver_regex = new RegExp( `^.+#${ semver_regex_str }$` );

const getLatestNpm = async( pkgName ) => {
const { stdout, stderr } = await execAsync( `npm show ${ pkgName } version` );
async function get_latest_npm( pkg_name ) {
const { stdout, stderr } = await exec_async( `npm show ${ pkg_name } version` );

if ( stderr ) {
throw new Error( stderr );
}

return stdout.trim();
};
}

const getLatestGit = async( version ) => {
async function get_latest_git( version ) {
const [ repo ] = version.split('#');

const destination = `${ storage }/${ repo }`;

await execAsync( `git clone [email protected]:${ repo } ${ destination }` );
await exec_async( `git clone [email protected]:${ repo } ${ destination }` );

const { stdout: latestTag } = await execAsync([
const { stdout: latest_tag } = await exec_async([
`cd ${ destination }`,
'&& git describe --tags `git rev-list --tags --max-count=1`'
].join(' ') );

return `${ repo }#${ latestTag.trim() }`;
};
return `${ repo }#${ latest_tag.trim() }`;
}

const getLatest = async([ pkgName, version ]) => {
async function get_latest([ pkg_name, version ]) {
let latest = version;

if ( gitSemverRegex.test( version ) ) {
latest = await getLatestGit( version );
} else if ( semverRegex.test( version ) ) {
latest = await getLatestNpm( pkgName );
if ( git_semver_regex.test( version ) ) {
latest = await get_latest_git( version );
} else if ( semver_regex.test( version ) ) {
latest = await get_latest_npm( pkg_name );
}

return [ pkgName, latest ];
};
return [ pkg_name, latest ];
}

const getPackageJSON = () => {
const pkgJSONPath = path.join( process.cwd(), 'package.json' );
function get_pkg_json() {
const pkg_json_path = path.join( process.cwd(), 'package.json' );

try {
return require( pkgJSONPath );
return require( pkg_json_path );
} catch ( ex ) {
if ( ex.code === 'MODULE_NOT_FOUND' ) {
throw new Error( `couldnt find package.json in current directory: ${ pkgJSONPath }` );
throw new Error( `couldnt find package.json in current directory: ${ pkg_json_path }` );
}
throw ex;
}
};
}

const upgradeDeps = async({ breaking, dryRun }) => {
async function upgrade_deps({ breaking, dryRun: dry_run }) {
try {
const packageJSON = getPackageJSON();
const pkg_json = get_pkg_json();

await execAsync( `[ ! -d ${ storage } ]` ).catch( () => {
await exec_async( `[ ! -d ${ storage } ]` ).catch( () => {
console.log( `State directory "${ storage }" must be deleted to continue` );
process.exit( 1 );
});

await execAsync( `mkdir -p ${ storage }` );
await exec_async( `mkdir -p ${ storage }` );

const depsPromise = Promise.all(
Object.entries( packageJSON.dependencies || {} ).map( getLatest )
const deps_promise = Promise.all(
Object.entries( pkg_json.dependencies || {} ).map( get_latest )
);

const devDepsPromise = Promise.all(
Object.entries( packageJSON.devDependencies || {} ).map( getLatest )
const dev_deps_promise = Promise.all(
Object.entries( pkg_json.devDependencies || {} ).map( get_latest )
);


const [ dependencies, devDependencies ] = await Promise.all([
depsPromise,
devDepsPromise
const [ dependencies, dev_dependencies ] = await Promise.all([
deps_promise,
dev_deps_promise
]);

const updated = Object.assign( {}, packageJSON );
const dryRunUpdates = { dependencies: {}, devDependencies: {} };
const updated = Object.assign( {}, pkg_json );
const dry_run_updates = { dependencies: {}, devDependencies: {} };

if ( dependencies.length ) {
updated.dependencies = Object.fromEntries(
dependencies.map( ([name, version]) => {
const prevVersion = packageJSON.dependencies[name];
const majorBump = prevVersion.split('.')[0] !== version.split('.')[0];
const newVersion = !majorBump || breaking ? version : prevVersion;
const prev_version = pkg_json.dependencies[name];
const major_bump = prev_version.split('.')[0] !== version.split('.')[0];
const new_version = !major_bump || breaking ? version : prev_version;

if ( prevVersion !== newVersion ) {
dryRunUpdates.dependencies[ name ] = `${ prevVersion } -> ${ newVersion }`;
if ( prev_version !== new_version ) {
dry_run_updates.dependencies[ name ] = `${ prev_version } -> ${ new_version }`;
}

return [name, newVersion];
return [name, new_version];
})
);
}

if ( devDependencies.length ) {
if ( dev_dependencies.length ) {
updated.devDependencies = Object.fromEntries(
devDependencies.map( ([name, version]) => {
const prevVersion = packageJSON.devDependencies[name];
const majorBump = prevVersion.split('.')[0] !== version.split('.')[0];
const newVersion = !majorBump || breaking ? version : prevVersion;
dev_dependencies.map( ([name, version]) => {
const prev_version = pkg_json.devDependencies[name];
const major_bump = prev_version.split('.')[0] !== version.split('.')[0];
const new_version = !major_bump || breaking ? version : prev_version;

if ( prevVersion !== newVersion ) {
dryRunUpdates.devDependencies[ name ] = `${ prevVersion } -> ${ newVersion }`;
if ( prev_version !== new_version ) {
dry_run_updates.devDependencies[ name ] = `${ prev_version } -> ${ new_version }`;
}

return [name, newVersion];
return [name, new_version];
})
);
}

if ( dryRun ) {
if ( dry_run ) {
console.log('Dry run package updates:\n');
console.log( JSON.stringify( dryRunUpdates, null, 2 ) );
console.log( JSON.stringify( dry_run_updates, null, 2 ) );
} else {
await writeFileAsync( 'package.json', JSON.stringify( updated, null, 2 ).trim() );
await write_file_async(
'package.json',
JSON.stringify( updated, null, 2 ).trim() + '\n'
);
}

await execAsync( `rm -rf ${ storage }` );
await exec_async( `rm -rf ${ storage }` );

process.exit( 0 );
} catch ( ex ) {
console.error( 'Failure upgrading deps', ex );

await execAsync( `rm -rf ${ storage }` );
await exec_async( `rm -rf ${ storage }` );

process.exit( 1 );
}
};
}

module.exports = upgradeDeps;
module.exports = upgrade_deps;
4 changes: 2 additions & 2 deletions lib/util/exec-async.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { exec } = require('child_process');
const { promisify } = require('util');

const execAsync = promisify( exec );
const exec_async = promisify( exec );

module.exports = execAsync;
module.exports = exec_async;
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "upgrade-deps",
"version": "0.3.3",
"version": "1.0.0",
"description": "CLI for automating updating package.json dependencies",
"main": "index.js",
"scripts": {
Expand All @@ -13,10 +13,10 @@
"upgrade-deps": "./bin/cli.js"
},
"dependencies": {
"commander": "9.1.0"
"commander": "9.4.1"
},
"devDependencies": {
"@edwmurph/eslint-config": "4.0.0"
"@edwmurph/eslint-config": "5.0.0"
},
"author": "edward",
"homepage": "https://github.com/edwmurph/upgrade-deps#readme",
Expand Down

0 comments on commit 5c6dc98

Please sign in to comment.