From 6115bdec21ac77ecbfa016d279b38bf5cda0edc6 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 13:37:11 +0000 Subject: [PATCH 1/7] feat: add support for running commands across project paths --- src/commands/cmd.js | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/commands/cmd.js diff --git a/src/commands/cmd.js b/src/commands/cmd.js new file mode 100644 index 0000000..28f7385 --- /dev/null +++ b/src/commands/cmd.js @@ -0,0 +1,102 @@ +const path = require('path'); +const ora = require('ora');const { terminal } = require('terminal-kit'); +const { execSync } = require('child_process'); + +const { findProjectPath, findAllProjectPaths } = require('./../utils/projectpaths'); +const { getPackage } = require('./../utils/get-package'); +const dirsExist = require('../utils/dirs-exist'); + + +const spinner = ora(); + + +exports.command = 'cmd [command]'; +exports.desc = 'Run a command within each project'; +exports.builder = (yargs) => { + + yargs.option('command', { + string: true, + demand: true, + }); + + yargs.option('continueOnFail', { + alias: 'F', + describe: 'Continue running the commands even on failure', + }); + + yargs.option('quiet', { + alias: 'q', + describe: 'Hide the output of stdout', + boolean: true, + }) + + yargs.demandOption('command', 'A command must be set'); +}; + +exports.handler = ({ + projects = '', + command, + continueOnFail, + quiet, +}) => { + const projectsList = projects.split(',').filter((item) => item.length > 0); + const hasTargetDirs = dirsExist(targetDirs); + const isAllProjects = hasTargetDirs && !projects; + + let paths = []; + + try { + if (projectsList.length === 0 && !isAllProjects) { + paths.push(path.resolve('./')); + } else if (isAllProjects) { + paths = findAllProjectPaths(targetDirs); + } else { + paths = projectsList.map((projectItem) => findProjectPath(projectItem, targetDirs)); + } + } catch (e) { + terminal.red(e); + process.exit(1); + } + + + let packages = []; + + try { + packages = paths.map((item) => getPackage(item, false)).filter((item) => item); + } catch (e) { + terminal.red(e); + process.exit(1); + } + + let fails = 0; + spinner.clear(); + spinner.start(`Running command '${command}'\n`); + packages.forEach((package) => { + + try { + execSync(command, { cwd: package.path, stdio: quiet ? 'pipe' : 'inherit' }); + spinner.succeed(); + } catch (err) { + spinner.fail(); + + if (!quiet) { + terminal.red(err.stderr); + } + + terminal('\n\n'); + + if (!continueOnFail) { + process.exit(1); + } + + fails += 1; + } + }); + + if (fails > 0) { + terminal.red('Some commands failed to execute\n'); + process.exit(1); + } + + process.exit(0); +} From f601762e66d986669f2655cefd957f3cd6a22ab8 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 13:45:02 +0000 Subject: [PATCH 2/7] feat: add support for defining the projects that runs the commands --- src/commands/cmd.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index 28f7385..59e8875 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -10,11 +10,16 @@ const dirsExist = require('../utils/dirs-exist'); const spinner = ora(); -exports.command = 'cmd [command]'; +exports.command = 'cmd [projects] [command]'; exports.desc = 'Run a command within each project'; exports.builder = (yargs) => { + yargs.positional('projects', { + describe: 'Comma separated list of projects to compile.', + type: 'string', + default: '', + }); - yargs.option('command', { + yargs.positional('command', { string: true, demand: true, }); From e9716087597d44d619a2853d81a117525a2115f8 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 13:54:02 +0000 Subject: [PATCH 3/7] fix: remove use of 'package' as it is a reserved word --- src/commands/cmd.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index 59e8875..8c4ce22 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -76,10 +76,10 @@ exports.handler = ({ let fails = 0; spinner.clear(); spinner.start(`Running command '${command}'\n`); - packages.forEach((package) => { + packages.forEach((pkg) => { try { - execSync(command, { cwd: package.path, stdio: quiet ? 'pipe' : 'inherit' }); + execSync(command, { cwd: pkg.path, stdio: quiet ? 'pipe' : 'inherit' }); spinner.succeed(); } catch (err) { spinner.fail(); From 8d45087ef13c74417b40aab201f16e8be302ebf7 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 15:36:47 +0000 Subject: [PATCH 4/7] style: update imports to be one per line --- src/commands/cmd.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index 8c4ce22..754e511 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -1,5 +1,6 @@ const path = require('path'); -const ora = require('ora');const { terminal } = require('terminal-kit'); +const ora = require('ora'); +const { terminal } = require('terminal-kit'); const { execSync } = require('child_process'); const { findProjectPath, findAllProjectPaths } = require('./../utils/projectpaths'); From 18c43e6354d411c5a08f7e1c07b1438bbc40c0d0 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 15:44:01 +0000 Subject: [PATCH 5/7] feat: update the expected syntax for the 'cmd' command --- src/commands/cmd.js | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index 754e511..2078076 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -11,44 +11,52 @@ const dirsExist = require('../utils/dirs-exist'); const spinner = ora(); -exports.command = 'cmd [projects] [command]'; +exports.command = 'cmd [projects] [options]'; exports.desc = 'Run a command within each project'; exports.builder = (yargs) => { - yargs.positional('projects', { - describe: 'Comma separated list of projects to compile.', + yargs.option('projects', { + describe: 'Comma separated list of projects to run the command on.', type: 'string', default: '', }); - yargs.positional('command', { - string: true, - demand: true, - }); - yargs.option('continueOnFail', { alias: 'F', describe: 'Continue running the commands even on failure', + type: 'boolean', }); yargs.option('quiet', { alias: 'q', describe: 'Hide the output of stdout', boolean: true, + type: 'boolean', }) - - yargs.demandOption('command', 'A command must be set'); }; exports.handler = ({ projects = '', - command, continueOnFail, quiet, + _: parts, + $0, }) => { const projectsList = projects.split(',').filter((item) => item.length > 0); const hasTargetDirs = dirsExist(targetDirs); const isAllProjects = hasTargetDirs && !projects; + parts.shift(); + + if (parts.length === 0) { + terminal.red().bold('Error: ') + .defaultColor('command cannot be empty\n'); + terminal.yellow('Usage: ') + .defaultColor(`${$0} cmd [projects] [opts] -- \n`); + process.exit(1); + } + + const command = parts.join(' '); + let paths = []; try { From 0f14399981d40610e140d4c8df27d20d4f897256 Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 16:16:50 +0000 Subject: [PATCH 6/7] feat: add `run` alias for `cmd` command --- src/commands/cmd.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index 2078076..a6b802e 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -12,6 +12,7 @@ const spinner = ora(); exports.command = 'cmd [projects] [options]'; +exports.aliases = 'run [projects] [options]'; exports.desc = 'Run a command within each project'; exports.builder = (yargs) => { yargs.option('projects', { From 960a1a5c3e9d25ca7723495b8c26c74141dbd38f Mon Sep 17 00:00:00 2001 From: Jerome Duncan Date: Mon, 13 Nov 2023 16:33:53 +0000 Subject: [PATCH 7/7] feat: if a cmd errors we should output the error even with quiet mode --- src/commands/cmd.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/commands/cmd.js b/src/commands/cmd.js index a6b802e..7900555 100644 --- a/src/commands/cmd.js +++ b/src/commands/cmd.js @@ -93,11 +93,7 @@ exports.handler = ({ spinner.succeed(); } catch (err) { spinner.fail(); - - if (!quiet) { - terminal.red(err.stderr); - } - + terminal.red(err.stderr); terminal('\n\n'); if (!continueOnFail) {