refactor: create exec.pnpm-cli-runner (#9064)

This commit is contained in:
Zoltan Kochan
2025-02-08 22:34:19 +01:00
committed by GitHub
parent 265946bb6d
commit c52f55af30
13 changed files with 147 additions and 57 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/exec.pnpm-cli-runner": major
---
Initial release.

View File

@@ -55,6 +55,7 @@
"@pnpm/deps.status": "workspace:*",
"@pnpm/env.path": "workspace:*",
"@pnpm/error": "workspace:*",
"@pnpm/exec.pnpm-cli-runner": "workspace:*",
"@pnpm/lifecycle": "workspace:*",
"@pnpm/log.group": "catalog:",
"@pnpm/package-bins": "workspace:*",

View File

@@ -1,40 +0,0 @@
import path from 'path'
import { sync as execSync } from 'execa'
export type InstallOptions = Array<'--production' | '--dev' | '--no-optional'>
export type InstallCommand = ['install', ...InstallOptions]
export interface Flags {
dev?: boolean
optional?: boolean
production?: boolean
}
export function createFromFlags (flags: Flags | undefined): InstallCommand {
const command: InstallCommand = ['install']
if (!flags) return command
const { dev, optional, production } = flags
if (production && !dev) {
command.push('--production')
} else if (dev && !production) {
command.push('--dev')
}
if (!optional) {
command.push('--no-optional')
}
return command
}
export function run (cwd: string, command: InstallCommand): void {
const execOpts = {
cwd,
stdio: 'inherit' as const,
}
if (path.basename(process.execPath) === 'pnpm') {
execSync(process.execPath, command, execOpts)
} else if (path.basename(process.argv[1]) === 'pnpm.cjs') {
execSync(process.execPath, [process.argv[1], ...command], execOpts)
} else {
execSync('pnpm', command, execOpts)
}
}

View File

@@ -1,9 +1,9 @@
import { type VerifyDepsBeforeRun } from '@pnpm/config'
import { PnpmError } from '@pnpm/error'
import { runPnpmCli } from '@pnpm/exec.pnpm-cli-runner'
import { globalWarn } from '@pnpm/logger'
import { checkDepsStatus, type CheckDepsStatusOptions, type WorkspaceStateSettings } from '@pnpm/deps.status'
import { prompt } from 'enquirer'
import * as installCommand from './installCommand'
export type RunDepsStatusCheckOptions = CheckDepsStatusOptions & { dir: string, verifyDepsBeforeRun?: VerifyDepsBeforeRun }
@@ -16,8 +16,8 @@ export async function runDepsStatusCheck (opts: RunDepsStatusCheckOptions): Prom
const { upToDate, issue, workspaceState } = await checkDepsStatus(opts)
if (upToDate) return
const command = installCommand.createFromFlags(workspaceState?.settings)
const install = installCommand.run.bind(null, opts.dir, command)
const command = ['install', ...createInstallArgs(workspaceState?.settings)]
const install = runPnpmCli.bind(null, command, { cwd: opts.dir })
switch (opts.verifyDepsBeforeRun) {
case 'install':
@@ -46,3 +46,18 @@ Would you like to run "pnpm ${command.join(' ')}" to update your "node_modules"?
break
}
}
export function createInstallArgs (opts: Pick<WorkspaceStateSettings, 'dev' | 'optional' | 'production'> | undefined): string[] {
const args: string[] = []
if (!opts) return args
const { dev, optional, production } = opts
if (production && !dev) {
args.push('--production')
} else if (dev && !production) {
args.push('--dev')
}
if (!optional) {
args.push('--no-optional')
}
return args
}

View File

@@ -0,0 +1,14 @@
import { createInstallArgs } from '../src/runDepsStatusCheck'
describe('createInstallArgs', () => {
test.each([
[{ production: true, optional: true }, ['--production']],
[{ production: true, optional: false }, ['--production', '--no-optional']],
[{ dev: true, optional: true }, ['--dev']],
[{ dev: true, optional: false }, ['--dev', '--no-optional']],
[{ production: true, dev: true, optional: true }, []],
[{ production: true, dev: true, optional: false }, ['--no-optional']],
])('%o -> %o', (opts, expected) => {
expect(createInstallArgs(opts)).toStrictEqual(expected)
})
})

View File

@@ -1,14 +0,0 @@
import { type Flags, type InstallCommand, createFromFlags } from '../src/installCommand'
describe(createFromFlags, () => {
test.each([
[{ production: true, optional: true }, ['install', '--production']],
[{ production: true, optional: false }, ['install', '--production', '--no-optional']],
[{ dev: true, optional: true }, ['install', '--dev']],
[{ dev: true, optional: false }, ['install', '--dev', '--no-optional']],
[{ production: true, dev: true, optional: true }, ['install']],
[{ production: true, dev: true, optional: false }, ['install', '--no-optional']],
] as Array<[Flags, InstallCommand]>)('%o -> %o', (flags, expected) => {
expect(createFromFlags(flags)).toStrictEqual(expected)
})
})

View File

@@ -86,6 +86,9 @@
},
{
"path": "../lifecycle"
},
{
"path": "../pnpm-cli-runner"
}
]
}

View File

@@ -0,0 +1,15 @@
# @pnpm/exec.pnpm-cli-runner
> Runs pnpm CLI
[![npm version](https://img.shields.io/npm/v/@pnpm/exec.pnpm-cli-runner.svg)](https://www.npmjs.com/package/@pnpm/exec.pnpm-cli-runner)
## Installation
```sh
pnpm add @pnpm/exec.pnpm-cli-runner
```
## License
MIT

View File

@@ -0,0 +1,42 @@
{
"name": "@pnpm/exec.pnpm-cli-runner",
"version": "1000.0.0-0",
"description": "Runs pnpm CLI",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib",
"!*.map"
],
"engines": {
"node": ">=18.12"
},
"scripts": {
"lint": "eslint \"src/**/*.ts\"",
"test": "pnpm run compile",
"prepublishOnly": "pnpm run compile",
"compile": "tsc --build && pnpm run lint --fix"
},
"repository": "https://github.com/pnpm/pnpm/blob/main/exec/pnpm-cli-runner",
"keywords": [
"pnpm10"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/pnpm/pnpm/issues"
},
"homepage": "https://github.com/pnpm/pnpm/blob/main/exec/pnpm-cli-runner#readme",
"devDependencies": {
"@pnpm/exec.pnpm-cli-runner": "workspace:*"
},
"dependencies": {
"execa": "catalog:"
},
"funding": "https://opencollective.com/pnpm",
"exports": {
".": "./lib/index.js"
},
"jest": {
"preset": "@pnpm/jest-config"
}
}

View File

@@ -0,0 +1,16 @@
import path from 'path'
import { sync as execSync } from 'execa'
export function runPnpmCli (command: string[], { cwd }: { cwd: string }): void {
const execOpts = {
cwd,
stdio: 'inherit' as const,
}
if (path.basename(process.execPath) === 'pnpm') {
execSync(process.execPath, command, execOpts)
} else if (path.basename(process.argv[1]) === 'pnpm.cjs') {
execSync(process.execPath, [process.argv[1], ...command], execOpts)
} else {
execSync('pnpm', command, execOpts)
}
}

View File

@@ -0,0 +1,12 @@
{
"extends": "@pnpm/tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": [
"src/**/*.ts",
"../../__typings__/**/*.d.ts"
],
"references": []
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../__typings__/**/*.d.ts"
]
}

13
pnpm-lock.yaml generated
View File

@@ -2448,6 +2448,9 @@ importers:
'@pnpm/error':
specifier: workspace:*
version: link:../../packages/error
'@pnpm/exec.pnpm-cli-runner':
specifier: workspace:*
version: link:../pnpm-cli-runner
'@pnpm/lifecycle':
specifier: workspace:*
version: link:../lifecycle
@@ -2555,6 +2558,16 @@ importers:
specifier: 'catalog:'
version: 5.0.0
exec/pnpm-cli-runner:
dependencies:
execa:
specifier: 'catalog:'
version: safe-execa@0.1.2
devDependencies:
'@pnpm/exec.pnpm-cli-runner':
specifier: workspace:*
version: 'link:'
exec/prepare-package:
dependencies:
'@pnpm/error':