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