mirror of
https://github.com/pnpm/pnpm.git
synced 2026-03-25 02:21:52 -04:00
"pnpm exec" currently works only when executed recursively, so it should fail with a meaningful error if "-r" is not present. close #2461
95 lines
2.4 KiB
TypeScript
95 lines
2.4 KiB
TypeScript
import { RecursiveSummary, throwOnCommandFail } from '@pnpm/cli-utils'
|
|
import { Config, types } from '@pnpm/config'
|
|
import PnpmError from '@pnpm/error'
|
|
import logger from '@pnpm/logger'
|
|
import sortPackages from '@pnpm/sort-packages'
|
|
import execa = require('execa')
|
|
import pLimit from 'p-limit'
|
|
import R = require('ramda')
|
|
import renderHelp = require('render-help')
|
|
|
|
export const commandNames = ['exec']
|
|
|
|
export function rcOptionsTypes () {
|
|
return R.pick([
|
|
'bail',
|
|
'sort',
|
|
'unsafe-perm',
|
|
'workspace-concurrency',
|
|
], types)
|
|
}
|
|
|
|
export const cliOptionsTypes = () => ({
|
|
...rcOptionsTypes(),
|
|
recursive: Boolean,
|
|
})
|
|
|
|
export function help () {
|
|
return renderHelp({
|
|
description: 'Run a command in each package.',
|
|
usages: ['-r exec -- <command> [args...]'],
|
|
})
|
|
}
|
|
|
|
export async function handler (
|
|
opts: Required<Pick<Config, 'selectedProjectsGraph'>> & {
|
|
bail?: boolean,
|
|
unsafePerm?: boolean,
|
|
rawConfig: object,
|
|
sort?: boolean,
|
|
workspaceConcurrency?: number,
|
|
} & Pick<Config, 'recursive'>,
|
|
params: string[],
|
|
) {
|
|
if (!opts.recursive) {
|
|
throw new PnpmError('EXEC_NOT_RECURSIVE', 'The "pnpm exec" command currently only works with the "-r" option')
|
|
}
|
|
const limitRun = pLimit(opts.workspaceConcurrency ?? 4)
|
|
|
|
const result = {
|
|
fails: [],
|
|
passes: 0,
|
|
} as RecursiveSummary
|
|
|
|
const chunks = opts.sort
|
|
? sortPackages(opts.selectedProjectsGraph)
|
|
: [Object.keys(opts.selectedProjectsGraph).sort()]
|
|
|
|
for (const chunk of chunks) {
|
|
await Promise.all(chunk.map((prefix: string) =>
|
|
limitRun(async () => {
|
|
try {
|
|
await execa(params[0], params.slice(1), {
|
|
cwd: prefix,
|
|
env: {
|
|
...process.env,
|
|
PNPM_PACKAGE_NAME: opts.selectedProjectsGraph[prefix].package.manifest.name,
|
|
},
|
|
stdio: 'inherit',
|
|
})
|
|
result.passes++
|
|
} catch (err) {
|
|
logger.info(err)
|
|
|
|
if (!opts.bail) {
|
|
result.fails.push({
|
|
error: err,
|
|
message: err.message,
|
|
prefix,
|
|
})
|
|
return
|
|
}
|
|
|
|
// tslint:disable:no-string-literal
|
|
err['code'] = 'ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL'
|
|
err['prefix'] = prefix
|
|
// tslint:enable:no-string-literal
|
|
throw err
|
|
}
|
|
},
|
|
)))
|
|
}
|
|
|
|
throwOnCommandFail('pnpm recursive exec', result)
|
|
}
|