diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index 0e051d36908ee..bacd9340ebfd1 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -1,6 +1,8 @@ -const { log, output } = require('proc-log') +const { output } = require('proc-log') const pkgJson = require('@npmcli/package-json') const BaseCommand = require('../base-cmd.js') +const { outputError } = require('../utils/output-error.js') +const { getError } = require('../utils/error-message.js') // TODO this is missing things like prepare, prepublishOnly, and dependencies const cmdList = [ @@ -55,9 +57,11 @@ class RunScript extends BaseCommand { async execWorkspaces (args) { await this.setWorkspaces() - for (const [name, path] of this.workspaces.entries()) { + const ws = [...this.workspaces.entries()] + for (const [name, path] of ws) { + const last = name === ws.at(-1)[0] if (!args.length) { - await this.#list(path, { workspace: name }) + await this.#list(path, { workspace: name, newline: !last }) continue } @@ -65,11 +69,21 @@ class RunScript extends BaseCommand { try { await this.#run(args, { path, pkg }) } catch (err) { - log.error(`Lifecycle script \`${args[0]}\` failed with error:`) - log.error(err) - log.error(` in workspace: ${pkg._id || pkg.name}`) - log.error(` at location: ${path}`) - process.exitCode = 1 + // Set command to null so that we get the full error parsing + // run-script will supress error messages due to isShellout + const error = getError(err, { npm: this.npm, command: null }) + outputError({ + ...error, + error: [ + ['', `Lifecycle script \`${args[0]}\` failed with error:`], + ['workspace', pkg._id || pkg.name], + ...error.error, + ], + }) + if (!last) { + output.error('') + } + process.exitCode = error.exitCode } } } @@ -133,7 +147,7 @@ class RunScript extends BaseCommand { } } - async #list (path, { workspace } = {}) { + async #list (path, { workspace, newline } = {}) { const { scripts = {}, name, _id } = await pkgJson.normalize(path).then(p => p.content) const scriptEntries = Object.entries(scripts) @@ -189,7 +203,9 @@ class RunScript extends BaseCommand { } } - output.standard('') + if (newline) { + output.standard('') + } } } diff --git a/tap-snapshots/test/lib/commands/run-script.js.test.cjs b/tap-snapshots/test/lib/commands/run-script.js.test.cjs index 2140adb6894c4..55c991bda10c3 100644 --- a/tap-snapshots/test/lib/commands/run-script.js.test.cjs +++ b/tap-snapshots/test/lib/commands/run-script.js.test.cjs @@ -31,11 +31,11 @@ postenv:echo after the env exports[`test/lib/commands/run-script.js TAP list scripts warn json > json report 1`] = ` { - test: 'exit 2', - start: 'node server.js', - stop: 'node kill-server.js', - preenv: 'echo before the env', - postenv: 'echo after the env' + "test": "exit 2", + "start": "node server.js", + "stop": "node kill-server.js", + "preenv": "echo before the env", + "postenv": "echo after the env" } ` @@ -53,20 +53,34 @@ Scripts available in x@1.2.3 via \`npm run-script\`: exports[`test/lib/commands/run-script.js TAP workspaces failed workspace run with succeeded runs > should log error msgs for each workspace script 1`] = ` Lifecycle script \`glorp\` failed with error: -Error: ERR - in workspace: a@1.0.0 - at location: {CWD}/prefix/packages/a +workspace a@1.0.0 +code ERR +ERR ` exports[`test/lib/commands/run-script.js TAP workspaces list all scripts --json > must match snapshot 1`] = ` -{ a: { glorp: 'echo a doing the glerp glop' } } -{ b: { glorp: 'echo b doing the glerp glop' } } { - c: { test: 'exit 0', posttest: 'echo posttest', lorem: 'echo c lorem' } + "a": { + "glorp": "echo a doing the glerp glop" + }, + "b": { + "glorp": "echo b doing the glerp glop" + }, + "c": { + "test": "exit 0", + "posttest": "echo posttest", + "lorem": "echo c lorem" + }, + "d": { + "test": "exit 0", + "posttest": "echo posttest" + }, + "e": { + "test": "exit 0", + "start": "echo start something" + }, + "noscripts": {} } -{ d: { test: 'exit 0', posttest: 'echo posttest' } } -{ e: { test: 'exit 0', start: 'echo start something' } } -{ noscripts: {} } ` exports[`test/lib/commands/run-script.js TAP workspaces list all scripts --parseable > must match snapshot 1`] = ` @@ -195,69 +209,60 @@ Scripts available in a@1.0.0 via \`npm run-script\`: exports[`test/lib/commands/run-script.js TAP workspaces missing scripts in all workspaces > should log error msgs for each workspace script 1`] = ` Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace a@1.0.0 +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: a@1.0.0 - at location: {CWD}/prefix/packages/a Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace b@2.0.0 +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: b@2.0.0 - at location: {CWD}/prefix/packages/b Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace c@1.0.0 +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: c@1.0.0 - at location: {CWD}/prefix/packages/c Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace d@1.0.0 +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: d@1.0.0 - at location: {CWD}/prefix/packages/d Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace e +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: e - at location: {CWD}/prefix/packages/e Lifecycle script \`missing-script\` failed with error: -Error: Missing script: "missing-script" - +workspace noscripts@1.0.0 +Missing script: "missing-script" +npm error To see a list of scripts, run: npm run - in workspace: noscripts@1.0.0 - at location: {CWD}/prefix/packages/noscripts ` exports[`test/lib/commands/run-script.js TAP workspaces missing scripts in some workspaces > should log error msgs for each workspace script 1`] = ` Lifecycle script \`test\` failed with error: -Error: Missing script: "test" - +workspace a@1.0.0 +Missing script: "test" +npm error To see a list of scripts, run: npm run - in workspace: a@1.0.0 - at location: {CWD}/prefix/packages/a Lifecycle script \`test\` failed with error: -Error: Missing script: "test" - +workspace b@2.0.0 +Missing script: "test" +npm error To see a list of scripts, run: npm run - in workspace: b@2.0.0 - at location: {CWD}/prefix/packages/b ` exports[`test/lib/commands/run-script.js TAP workspaces single failed workspace run > should log error msgs for each workspace script 1`] = ` Lifecycle script \`test\` failed with error: -Error: err - in workspace: c@1.0.0 - at location: {CWD}/prefix/packages/c +workspace c@1.0.0 +err `