2021-02-23 17:29:16 -05:00
|
|
|
const runScript = require('@npmcli/run-script')
|
|
|
|
const { isServerPackage } = runScript
|
2020-10-02 17:52:19 -04:00
|
|
|
const readJson = require('read-package-json-fast')
|
|
|
|
const { resolve } = require('path')
|
|
|
|
const output = require('./utils/output.js')
|
|
|
|
const log = require('npmlog')
|
2021-03-04 17:40:28 -05:00
|
|
|
const usageUtil = require('./utils/usage.js')
|
|
|
|
const didYouMean = require('./utils/did-you-mean.js')
|
2020-10-02 17:52:19 -04:00
|
|
|
const isWindowsShell = require('./utils/is-windows-shell.js')
|
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const cmdList = [
|
|
|
|
'publish',
|
|
|
|
'install',
|
|
|
|
'uninstall',
|
|
|
|
'test',
|
|
|
|
'stop',
|
|
|
|
'start',
|
|
|
|
'restart',
|
|
|
|
'version',
|
|
|
|
].reduce((l, p) => l.concat(['pre' + p, p, 'post' + p]), [])
|
|
|
|
|
|
|
|
class RunScript {
|
|
|
|
constructor (npm) {
|
|
|
|
this.npm = npm
|
2011-11-21 09:48:45 -08:00
|
|
|
}
|
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
/* istanbul ignore next - see test/lib/load-all-commands.js */
|
|
|
|
get usage () {
|
|
|
|
return usageUtil(
|
|
|
|
'run-script',
|
|
|
|
'npm run-script <command> [-- <args>]'
|
|
|
|
)
|
|
|
|
}
|
2011-11-21 09:48:45 -08:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
async completion (opts) {
|
|
|
|
const argv = opts.conf.argv.remain
|
|
|
|
if (argv.length === 2) {
|
|
|
|
// find the script name
|
|
|
|
const json = resolve(this.npm.localPrefix, 'package.json')
|
|
|
|
const { scripts = {} } = await readJson(json).catch(er => ({}))
|
|
|
|
return Object.keys(scripts)
|
|
|
|
}
|
|
|
|
}
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
exec (args, cb) {
|
|
|
|
if (args.length)
|
|
|
|
this.run(args).then(() => cb()).catch(cb)
|
|
|
|
else
|
|
|
|
this.list(args).then(() => cb()).catch(cb)
|
|
|
|
}
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
async run (args) {
|
|
|
|
const path = this.npm.localPrefix
|
|
|
|
const event = args.shift()
|
|
|
|
const { scriptShell } = this.npm.flatOptions
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const pkg = await readJson(`${path}/package.json`)
|
|
|
|
const { scripts = {} } = pkg
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (event === 'restart' && !scripts.restart)
|
|
|
|
scripts.restart = 'npm stop --if-present && npm start'
|
|
|
|
else if (event === 'env' && !scripts.env)
|
|
|
|
scripts.env = isWindowsShell ? 'SET' : 'env'
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
pkg.scripts = scripts
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (
|
|
|
|
!Object.prototype.hasOwnProperty.call(scripts, event) &&
|
|
|
|
!(event === 'start' && await isServerPackage(path))
|
|
|
|
) {
|
|
|
|
if (this.npm.config.get('if-present'))
|
|
|
|
return
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const suggestions = didYouMean(event, Object.keys(scripts))
|
|
|
|
throw new Error(`missing script: ${event}${
|
|
|
|
suggestions ? `\n${suggestions}` : ''}`)
|
|
|
|
}
|
2014-09-24 14:41:07 -07:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
// positional args only added to the main event, not pre/post
|
|
|
|
const events = [[event, args]]
|
|
|
|
if (!this.npm.flatOptions.ignoreScripts) {
|
|
|
|
if (scripts[`pre${event}`])
|
|
|
|
events.unshift([`pre${event}`, []])
|
|
|
|
|
|
|
|
if (scripts[`post${event}`])
|
|
|
|
events.push([`post${event}`, []])
|
|
|
|
}
|
2011-11-21 09:48:45 -08:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const opts = {
|
|
|
|
path,
|
2020-11-01 07:54:36 +01:00
|
|
|
args,
|
2021-03-04 17:40:28 -05:00
|
|
|
scriptShell,
|
|
|
|
stdio: 'inherit',
|
|
|
|
stdioString: true,
|
|
|
|
pkg,
|
|
|
|
banner: log.level !== 'silent',
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const [event, args] of events) {
|
|
|
|
await runScript({
|
|
|
|
...opts,
|
|
|
|
event,
|
|
|
|
args,
|
|
|
|
})
|
|
|
|
}
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
2011-11-21 09:48:45 -08:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
async list () {
|
|
|
|
const path = this.npm.localPrefix
|
|
|
|
const { scripts, name } = await readJson(`${path}/package.json`)
|
2014-05-05 18:20:40 -07:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (!scripts)
|
|
|
|
return []
|
2014-05-05 18:20:40 -07:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const allScripts = Object.keys(scripts)
|
|
|
|
if (log.level === 'silent')
|
|
|
|
return allScripts
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (this.npm.flatOptions.json) {
|
|
|
|
output(JSON.stringify(scripts, null, 2))
|
|
|
|
return allScripts
|
|
|
|
}
|
2014-11-04 15:08:12 -08:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (this.npm.flatOptions.parseable) {
|
|
|
|
for (const [script, cmd] of Object.entries(scripts))
|
|
|
|
output(`${script}:${cmd}`)
|
2014-11-04 15:08:12 -08:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
return allScripts
|
|
|
|
}
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
const indent = '\n '
|
|
|
|
const prefix = ' '
|
|
|
|
const cmds = []
|
|
|
|
const runScripts = []
|
|
|
|
for (const script of allScripts) {
|
|
|
|
const list = cmdList.includes(script) ? cmds : runScripts
|
|
|
|
list.push(script)
|
|
|
|
}
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (cmds.length)
|
|
|
|
output(`Lifecycle scripts included in ${name}:`)
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
for (const script of cmds)
|
|
|
|
output(prefix + script + indent + scripts[script])
|
2020-11-01 07:54:36 +01:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
if (!cmds.length && runScripts.length)
|
|
|
|
output(`Scripts available in ${name} via \`npm run-script\`:`)
|
|
|
|
else if (runScripts.length)
|
|
|
|
output('\navailable via `npm run-script`:')
|
|
|
|
|
|
|
|
for (const script of runScripts)
|
|
|
|
output(prefix + script + indent + scripts[script])
|
2014-09-24 14:41:07 -07:00
|
|
|
|
2021-03-04 17:40:28 -05:00
|
|
|
return allScripts
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = RunScript
|