All files explore.js

97.67% Statements 42/43
100% Branches 12/12
80% Functions 4/5
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67      2x 2x 2x   8x   2x 2x 2x 2x 2x 2x   2x   2x 2x 2x   2x 8x 1x     7x 7x 7x   7x 7x 3x 1x 1x 1x   2x       7x 1x     6x 6x   6x 4x     6x     6x 6x 6x 6x   6x       2x  
// npm explore <pkg>[@<version>]
// open a subshell to the package folder.
 
const usageUtil = require('./utils/usage.js')
const completion = require('./utils/completion/installed-shallow.js')
const usage = usageUtil('explore', 'npm explore <pkg> [ -- <command>]')
 
const cmd = (args, cb) => explore(args).then(() => cb()).catch(cb)
 
const output = require('./utils/output.js')
const npm = require('./npm.js')
const isWindows = require('./utils/is-windows.js')
const escapeArg = require('./utils/escape-arg.js')
const escapeExecPath = require('./utils/escape-exec-path.js')
const log = require('npmlog')
 
const spawn = require('@npmcli/promise-spawn')
 
const { resolve } = require('path')
const { promisify } = require('util')
const stat = promisify(require('fs').stat)
 
const explore = async args => {
  if (args.length < 1 || !args[0]) {
    throw usage
  }
 
  const pkg = args.shift()
  const cwd = resolve(npm.dir, pkg)
  const opts = { cwd, stdio: 'inherit', stdioString: true }
 
  const shellArgs = []
  if (args.length) {
    if (isWindows) {
      const execCmd = escapeExecPath(args.shift())
      opts.windowsVerbatimArguments = true
      shellArgs.push('/d', '/s', '/c', execCmd, ...args.map(escapeArg))
    } else {
      shellArgs.push('-c', args.map(escapeArg).join(' ').trim())
    }
  }
 
  await stat(cwd).catch(er => {
    throw new Error(`It doesn't look like ${pkg} is installed.`)
  })
 
  const sh = npm.flatOptions.shell
  log.disableProgress()
 
  if (!shellArgs.length) {
    output(`\nExploring ${cwd}\nType 'exit' or ^D when finished\n`)
  }
 
  log.silly('explore', {sh, shellArgs, opts})
 
  // only noisily fail if non-interactive, but still keep exit code intact
  const proc = spawn(sh, shellArgs, opts)
  try {
    const res = await (shellArgs.length ? proc : proc.catch(er => er))
    process.exitCode = res.code
  } finally {
    log.enableProgress()
  }
}
 
module.exports = Object.assign(cmd, { completion, usage })