codekingpro/portable-devtools
115k
1const ciInfo = require('ci-info')
2const runScript = require('@npmcli/run-script')
3const pkgJson = require('@npmcli/package-json')
4const { log, output } = require('proc-log')
5const noTTY = require('./no-tty.js')
6const isWindowsShell = require('./is-windows.js')
7
8const run = async ({
9 args,
10 call,
11 flatOptions,
12 locationMsg,
13 path,
14 binPaths,
15 runPath,
16 scriptShell,
17}) => {
18 // escape executable path
19 // necessary for preventing bash/cmd keywords from overriding
20 if (!isWindowsShell) {
21 if (args.length > 0) {
22 args[0] = '"' + args[0] + '"'
23 }
24 }
25
26 // turn list of args into command string
27 const script = call || args.shift() || scriptShell
28
29 // do the fakey runScript dance
30 // still should work if no package.json in cwd
31 const { content: realPkg } = await pkgJson.normalize(path, { steps: [
32 'binDir',
33 ...pkgJson.normalizeSteps,
34 ] }).catch(() => ({ content: {} }))
35 const pkg = {
36 ...realPkg,
37 scripts: {
38 ...(realPkg.scripts || {}),
39 npx: script,
40 },
41 }
42
43 if (script === scriptShell) {
44 if (!noTTY()) {
45 if (ciInfo.isCI) {
46 return log.warn('exec', 'Interactive mode disabled in CI environment')
47 }
48
49 const { chalk } = flatOptions
50
51 output.standard(`${
52 chalk.reset('\nEntering npm script environment')
53 }${
54 chalk.reset(locationMsg || ` at location:\n${chalk.dim(runPath)}`)
55 }${
56 chalk.bold('\nType \'exit\' or ^D when finished\n')
57 }`)
58 }
59 }
60 return runScript({
61 ...flatOptions,
62 pkg,
63 // we always run in cwd, not --prefix
64 path: runPath,
65 binPaths,
66 event: 'npx',
67 args,
68 stdio: 'inherit',
69 scriptShell,
70 })
71}
72
73module.exports = run
74 