mirror of
https://github.com/pnpm/pnpm.git
synced 2026-01-06 22:18:17 -05:00
feat: dlx (#3652)
This commit is contained in:
6
.changeset/polite-dolls-wink.md
Normal file
6
.changeset/polite-dolls-wink.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-script-runners": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
New command added for running packages in a tempory environment: `pnpm dlx <command> ...`
|
||||
@@ -50,6 +50,7 @@
|
||||
"@pnpm/lifecycle": "workspace:11.0.4",
|
||||
"@pnpm/read-project-manifest": "workspace:2.0.5",
|
||||
"@pnpm/sort-packages": "workspace:2.1.1",
|
||||
"@pnpm/store-path": "^5.0.0",
|
||||
"@pnpm/types": "workspace:7.4.0",
|
||||
"p-limit": "^3.1.0",
|
||||
"path-exists": "^4.0.0",
|
||||
|
||||
73
packages/plugin-commands-script-runners/src/dlx.ts
Normal file
73
packages/plugin-commands-script-runners/src/dlx.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import storePath from '@pnpm/store-path'
|
||||
import rimraf from '@zkochan/rimraf'
|
||||
import execa from 'execa'
|
||||
import PATH from 'path-name'
|
||||
import renderHelp from 'render-help'
|
||||
|
||||
export const commandNames = ['dlx']
|
||||
|
||||
export function rcOptionsTypes () {
|
||||
return {}
|
||||
}
|
||||
|
||||
export const cliOptionsTypes = () => ({
|
||||
package: String,
|
||||
})
|
||||
|
||||
export function help () {
|
||||
return renderHelp({
|
||||
description: 'Run a package in a temporary environment.',
|
||||
descriptionLists: [
|
||||
{
|
||||
title: 'Options',
|
||||
|
||||
list: [
|
||||
{
|
||||
description: 'The package to install before running the command',
|
||||
name: '--package',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
usages: ['pnpm dlx <command> [args...]'],
|
||||
})
|
||||
}
|
||||
|
||||
export async function handler (
|
||||
opts: {
|
||||
package?: string
|
||||
},
|
||||
params: string[]
|
||||
) {
|
||||
const cache = path.join(await storePath(process.cwd(), '~/.pnpm-store'), 'tmp')
|
||||
const prefix = path.join(cache, `dlx-${process.pid.toString()}`)
|
||||
const bins = process.platform === 'win32'
|
||||
? prefix
|
||||
: path.join(prefix, 'bin')
|
||||
fs.mkdirSync(prefix, { recursive: true })
|
||||
process.on('exit', () => {
|
||||
try {
|
||||
fs.rmdirSync(prefix, {
|
||||
recursive: true,
|
||||
maxRetries: 3,
|
||||
})
|
||||
} catch (err) { }
|
||||
})
|
||||
await rimraf(bins)
|
||||
const pkg = opts.package ?? params[0]
|
||||
await execa('pnpm', ['add', pkg, '--global', '--global-dir', prefix, '--dir', prefix], {
|
||||
stdio: 'inherit',
|
||||
})
|
||||
await execa(params[0], params.slice(1), {
|
||||
env: {
|
||||
...process.env,
|
||||
[PATH]: [
|
||||
bins,
|
||||
process.env[PATH],
|
||||
].join(path.delimiter),
|
||||
},
|
||||
stdio: 'inherit',
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as dlx from './dlx'
|
||||
import * as exec from './exec'
|
||||
import * as restart from './restart'
|
||||
import * as run from './run'
|
||||
@@ -8,4 +9,4 @@ const test = {
|
||||
..._test,
|
||||
}
|
||||
|
||||
export { exec, restart, run, test }
|
||||
export { dlx, exec, restart, run, test }
|
||||
|
||||
21
packages/plugin-commands-script-runners/test/dlx.ts
Normal file
21
packages/plugin-commands-script-runners/test/dlx.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import fs from 'fs'
|
||||
import { dlx } from '@pnpm/plugin-commands-script-runners'
|
||||
import { prepareEmpty } from '@pnpm/prepare'
|
||||
|
||||
test('dlx', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
await dlx.handler({}, ['touch', 'foo'])
|
||||
|
||||
expect(fs.existsSync('foo')).toBeTruthy()
|
||||
})
|
||||
|
||||
test('dlx --package <pkg>', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
await dlx.handler({
|
||||
package: 'zkochan/for-testing-pnpm-dlx',
|
||||
}, ['foo'])
|
||||
|
||||
expect(fs.existsSync('foo')).toBeTruthy()
|
||||
})
|
||||
@@ -9,6 +9,7 @@ import { outdated } from '@pnpm/plugin-commands-outdated'
|
||||
import { pack, publish } from '@pnpm/plugin-commands-publishing'
|
||||
import { rebuild } from '@pnpm/plugin-commands-rebuild'
|
||||
import {
|
||||
dlx,
|
||||
exec,
|
||||
restart,
|
||||
run,
|
||||
@@ -62,6 +63,7 @@ const commands: Array<{
|
||||
add,
|
||||
audit,
|
||||
bin,
|
||||
dlx,
|
||||
env,
|
||||
exec,
|
||||
fetch,
|
||||
|
||||
@@ -17,7 +17,7 @@ const RENAMED_OPTIONS = {
|
||||
export default async function parseCliArgs (inputArgv: string[]) {
|
||||
return parseCliArgsLib({
|
||||
fallbackCommand: 'run',
|
||||
escapeArgs: ['exec'],
|
||||
escapeArgs: ['dlx', 'exec'],
|
||||
getCommandLongName: getCommandFullName,
|
||||
getTypesByCommandName: getCliOptionsTypes,
|
||||
renamedOptions: RENAMED_OPTIONS,
|
||||
|
||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@@ -2275,6 +2275,7 @@ importers:
|
||||
'@pnpm/prepare': workspace:0.0.26
|
||||
'@pnpm/read-project-manifest': workspace:2.0.5
|
||||
'@pnpm/sort-packages': workspace:2.1.1
|
||||
'@pnpm/store-path': ^5.0.0
|
||||
'@pnpm/types': workspace:7.4.0
|
||||
'@types/ramda': 0.27.39
|
||||
'@zkochan/rimraf': ^2.1.1
|
||||
@@ -2296,6 +2297,7 @@ importers:
|
||||
'@pnpm/lifecycle': link:../lifecycle
|
||||
'@pnpm/read-project-manifest': link:../read-project-manifest
|
||||
'@pnpm/sort-packages': link:../sort-packages
|
||||
'@pnpm/store-path': 5.0.0
|
||||
'@pnpm/types': link:../types
|
||||
p-limit: 3.1.0
|
||||
path-exists: 4.0.0
|
||||
|
||||
Reference in New Issue
Block a user