| 6 | const isWindowsShell = require('./is-windows.js') |
| 7 | |
| 8 | const 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 | // single-quote so shell metacharacters in the executable name are taken |
| 23 | // literally; double quotes still expand $(), backticks, $var and " |
| 24 | args[0] = `'${args[0].replace(/'/g, `'\\''`)}'` |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | // turn list of args into command string |
| 29 | const script = call || args.shift() || scriptShell |
| 30 | |
| 31 | // do the fakey runScript dance |
| 32 | // still should work if no package.json in cwd |
| 33 | const { content: realPkg } = await pkgJson.normalize(path, { steps: [ |
| 34 | 'binDir', |
| 35 | ...pkgJson.normalizeSteps, |
| 36 | ] }).catch(() => ({ content: {} })) |
| 37 | const pkg = { |
| 38 | ...realPkg, |
| 39 | scripts: { |
| 40 | ...(realPkg.scripts || {}), |
| 41 | npx: script, |
| 42 | }, |
| 43 | } |
| 44 | |
| 45 | if (script === scriptShell) { |
| 46 | if (!noTTY()) { |
| 47 | if (ciInfo.isCI) { |
| 48 | return log.warn('exec', 'Interactive mode disabled in CI environment') |
| 49 | } |
| 50 | |
| 51 | const { chalk } = flatOptions |
| 52 | |
| 53 | output.standard(`${ |
| 54 | chalk.reset('\nEntering npm script environment') |
| 55 | }${ |
| 56 | chalk.reset(locationMsg || ` at location:\n${chalk.dim(runPath)}`) |
| 57 | }${ |
| 58 | chalk.bold('\nType \'exit\' or ^D when finished\n') |
| 59 | }`) |
| 60 | } |
| 61 | } |
| 62 | return runScript({ |
| 63 | ...flatOptions, |
| 64 | pkg, |
| 65 | // we always run in cwd, not --prefix |