From 39e4da0358ce44858117921b2aabe271ebcee797 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Fri, 12 Apr 2024 16:09:13 -0700 Subject: [PATCH] feat(libnpmexec)!: no longer accept output function BREAKING CHANGE: libnpmexec now emits an output event on process instead of invoking the output function passed in --- workspaces/libnpmexec/README.md | 1 - workspaces/libnpmexec/lib/index.js | 2 - workspaces/libnpmexec/lib/run-script.js | 5 +- workspaces/libnpmexec/test/run-script.js | 61 ++++++++++++------------ 4 files changed, 32 insertions(+), 37 deletions(-) diff --git a/workspaces/libnpmexec/README.md b/workspaces/libnpmexec/README.md index fb4a1e32b18df..acd037c110b4b 100644 --- a/workspaces/libnpmexec/README.md +++ b/workspaces/libnpmexec/README.md @@ -35,7 +35,6 @@ await libexec({ - `localBin`: Location to the `node_modules/.bin` folder of the local project to start scanning for bin files **String**, defaults to `./node_modules/.bin`. **libexec** will walk up the directory structure looking for `node_modules/.bin` folders in parent folders that might satisfy the current `arg` and will use that bin if found. - `locationMsg`: Overrides "at location" message when entering interactive mode **String** - `globalBin`: Location to the global space bin folder, same as: `$(npm bin -g)` **String**, defaults to empty string. - - `output`: A function to print output to **Function** - `packages`: A list of packages to be used (possibly fetch from the registry) **Array**, defaults to `[]` - `path`: Location to where to read local project info (`package.json`) **String**, defaults to `.` - `runPath`: Location to where to execute the script **String**, defaults to `.` diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js index 8d7dfa27dd42b..944f34b01c237 100644 --- a/workspaces/libnpmexec/lib/index.js +++ b/workspaces/libnpmexec/lib/index.js @@ -83,7 +83,6 @@ const exec = async (opts) => { locationMsg = undefined, globalBin = '', globalPath, - output, // dereference values because we manipulate it later packages: [...packages] = [], path = '.', @@ -98,7 +97,6 @@ const exec = async (opts) => { call, flatOptions, locationMsg, - output, path, binPaths, runPath, diff --git a/workspaces/libnpmexec/lib/run-script.js b/workspaces/libnpmexec/lib/run-script.js index e85bae81080cd..1f621edcbc9aa 100644 --- a/workspaces/libnpmexec/lib/run-script.js +++ b/workspaces/libnpmexec/lib/run-script.js @@ -1,7 +1,7 @@ const ciInfo = require('ci-info') const runScript = require('@npmcli/run-script') const readPackageJson = require('read-package-json-fast') -const { log } = require('proc-log') +const { log, output } = require('proc-log') const noTTY = require('./no-tty.js') const run = async ({ @@ -9,7 +9,6 @@ const run = async ({ call, flatOptions, locationMsg, - output = () => {}, path, binPaths, runPath, @@ -37,7 +36,7 @@ const run = async ({ const { chalk } = flatOptions - output(`${ + output.standard(`${ chalk.reset('\nEntering npm script environment') }${ chalk.reset(locationMsg || ` at location:\n${chalk.dim(runPath)}`) diff --git a/workspaces/libnpmexec/test/run-script.js b/workspaces/libnpmexec/test/run-script.js index 1197b0a6da0aa..01e3f35594906 100644 --- a/workspaces/libnpmexec/test/run-script.js +++ b/workspaces/libnpmexec/test/run-script.js @@ -1,9 +1,26 @@ const t = require('tap') const mockRunScript = async (t, mocks, { level = 0 } = {}) => { - const runScript = t.mock('../lib/run-script.js', mocks) + const mockedRunScript = t.mock('../lib/run-script.js', mocks) const { Chalk } = await import('chalk') - return (opts) => runScript({ + + const outputs = [] + const handleOutput = (_level, msg) => { + if (_level === 'standard') { + outputs.push(msg) + } + } + process.on('output', handleOutput) + t.teardown(() => process.off('output', handleOutput)) + + const logs = [] + const handleLog = (_level, title, msg) => { + logs.push(`${_level} ${title} ${msg}`) + } + process.on('log', handleLog) + t.teardown(() => process.off('log', handleLog)) + + const runScript = (opts) => mockedRunScript({ args: [], call: '', path: '', @@ -14,6 +31,7 @@ const mockRunScript = async (t, mocks, { level = 0 } = {}) => { ...opts, flatOptions: { chalk: new Chalk({ level }) }, }) + return { runScript, outputs, logs } } t.test('no package.json', async t => { @@ -24,7 +42,7 @@ t.test('no package.json', async t => { name: 'pkg', }), }) - const runScript = await mockRunScript(t, { + const { runScript } = await mockRunScript(t, { 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') @@ -38,7 +56,7 @@ t.test('no package.json', async t => { t.test('colorized interactive mode msg', async t => { t.plan(2) - const runScript = await mockRunScript(t, { + const { runScript, outputs } = await mockRunScript(t, { 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') @@ -46,20 +64,16 @@ t.test('colorized interactive mode msg', async t => { '../lib/no-tty.js': () => false, }, { level: 3 }) - const OUTPUT = [] await runScript({ - output: msg => { - OUTPUT.push(msg) - }, runPath: '/foo/', }) - t.matchSnapshot(OUTPUT.join('\n'), 'should print colorized output') + t.matchSnapshot(outputs.join('\n'), 'should print colorized output') }) t.test('no color interactive mode msg', async t => { t.plan(2) - const runScript = await mockRunScript(t, { + const { runScript, outputs } = await mockRunScript(t, { 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') @@ -67,20 +81,16 @@ t.test('no color interactive mode msg', async t => { '../lib/no-tty.js': () => false, }) - const OUTPUT = [] await runScript({ - output: msg => { - OUTPUT.push(msg) - }, runPath: '/foo/', }) - t.matchSnapshot(OUTPUT.join('\n'), 'should print non-colorized output') + t.matchSnapshot(outputs.join('\n'), 'should print non-colorized output') }) t.test('no tty', async t => { t.plan(1) - const runScript = await mockRunScript(t, { + const { runScript } = await mockRunScript(t, { 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') @@ -92,27 +102,16 @@ t.test('no tty', async t => { }) t.test('ci env', async t => { - t.plan(2) - - const runScript = await mockRunScript(t, { + const { runScript, logs } = await mockRunScript(t, { 'ci-info': { isCI: true }, '@npmcli/run-script': async () => { throw new Error('should not call run-script') }, '../lib/no-tty.js': () => false, - 'proc-log': { - log: { - warn (title, msg) { - t.equal(title, 'exec', 'should have expected title') - t.equal( - msg, - 'Interactive mode disabled in CI environment', - 'should have expected ci environment message' - ) - }, - }, - }, + }) await runScript() + + t.equal(logs[0], 'warn exec Interactive mode disabled in CI environment') })