2011-11-21 09:48:45 -08:00
|
|
|
module.exports = runScript
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
var lifecycle = require('./utils/lifecycle.js')
|
|
|
|
var npm = require('./npm.js')
|
|
|
|
var path = require('path')
|
|
|
|
var readJson = require('read-package-json')
|
|
|
|
var log = require('npmlog')
|
|
|
|
var chain = require('slide').chain
|
2016-05-06 15:22:02 -07:00
|
|
|
var usage = require('./utils/usage')
|
2016-06-24 13:43:51 -07:00
|
|
|
var output = require('./utils/output.js')
|
2018-07-18 13:55:52 -07:00
|
|
|
var didYouMean = require('./utils/did-you-mean')
|
|
|
|
var isWindowsShell = require('./utils/is-windows-shell.js')
|
2011-11-21 09:48:45 -08:00
|
|
|
|
2016-05-06 15:22:02 -07:00
|
|
|
runScript.usage = usage(
|
|
|
|
'run-script',
|
|
|
|
'npm run-script <command> [-- <args>...]'
|
|
|
|
)
|
2011-11-21 09:48:45 -08:00
|
|
|
|
|
|
|
runScript.completion = function (opts, cb) {
|
|
|
|
// see if there's already a package specified.
|
|
|
|
var argv = opts.conf.argv.remain
|
|
|
|
|
|
|
|
if (argv.length >= 4) return cb()
|
|
|
|
|
|
|
|
if (argv.length === 3) {
|
|
|
|
// either specified a script locally, in which case, done,
|
|
|
|
// or a package, in which case, complete against its scripts
|
2015-10-09 23:13:57 -07:00
|
|
|
var json = path.join(npm.localPrefix, 'package.json')
|
2011-11-21 09:48:45 -08:00
|
|
|
return readJson(json, function (er, d) {
|
2015-10-09 23:13:57 -07:00
|
|
|
if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
|
2011-11-21 09:48:45 -08:00
|
|
|
if (er) d = {}
|
|
|
|
var scripts = Object.keys(d.scripts || {})
|
2015-10-09 23:13:57 -07:00
|
|
|
console.error('local scripts', scripts)
|
2011-11-21 09:48:45 -08:00
|
|
|
if (scripts.indexOf(argv[2]) !== -1) return cb()
|
|
|
|
// ok, try to find out which package it was, then
|
2015-10-09 23:13:57 -07:00
|
|
|
var pref = npm.config.get('global') ? npm.config.get('prefix')
|
2018-04-20 18:26:37 -07:00
|
|
|
: npm.localPrefix
|
2015-10-09 23:13:57 -07:00
|
|
|
var pkgDir = path.resolve(pref, 'node_modules', argv[2], 'package.json')
|
2011-11-21 09:48:45 -08:00
|
|
|
readJson(pkgDir, function (er, d) {
|
2015-10-09 23:13:57 -07:00
|
|
|
if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
|
2011-11-21 09:48:45 -08:00
|
|
|
if (er) d = {}
|
|
|
|
var scripts = Object.keys(d.scripts || {})
|
|
|
|
return cb(null, scripts)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
readJson(path.join(npm.localPrefix, 'package.json'), function (er, d) {
|
|
|
|
if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
|
2011-11-21 09:48:45 -08:00
|
|
|
d = d || {}
|
2015-05-22 03:14:39 -04:00
|
|
|
cb(null, Object.keys(d.scripts || {}))
|
2011-11-21 09:48:45 -08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function runScript (args, cb) {
|
2014-05-05 18:20:40 -07:00
|
|
|
if (!args.length) return list(cb)
|
2014-09-24 14:41:07 -07:00
|
|
|
|
|
|
|
var pkgdir = npm.localPrefix
|
2015-10-09 23:13:57 -07:00
|
|
|
var cmd = args.shift()
|
2011-11-21 09:48:45 -08:00
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
readJson(path.resolve(pkgdir, 'package.json'), function (er, d) {
|
2011-11-21 09:48:45 -08:00
|
|
|
if (er) return cb(er)
|
2014-09-24 14:41:07 -07:00
|
|
|
run(d, pkgdir, cmd, args, cb)
|
2011-11-21 09:48:45 -08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
function list (cb) {
|
|
|
|
var json = path.join(npm.localPrefix, 'package.json')
|
|
|
|
var cmdList = [
|
|
|
|
'publish',
|
|
|
|
'install',
|
|
|
|
'uninstall',
|
|
|
|
'test',
|
|
|
|
'stop',
|
|
|
|
'start',
|
|
|
|
'restart',
|
|
|
|
'version'
|
|
|
|
].reduce(function (l, p) {
|
|
|
|
return l.concat(['pre' + p, p, 'post' + p])
|
|
|
|
}, [])
|
|
|
|
return readJson(json, function (er, d) {
|
|
|
|
if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
|
2014-05-05 18:20:40 -07:00
|
|
|
if (er) d = {}
|
2015-03-06 02:57:32 -06:00
|
|
|
var allScripts = Object.keys(d.scripts || {})
|
|
|
|
var scripts = []
|
|
|
|
var runScripts = []
|
|
|
|
allScripts.forEach(function (script) {
|
|
|
|
if (cmdList.indexOf(script) !== -1) scripts.push(script)
|
|
|
|
else runScripts.push(script)
|
|
|
|
})
|
2014-05-05 18:20:40 -07:00
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
if (log.level === 'silent') {
|
2015-03-06 02:57:32 -06:00
|
|
|
return cb(null, allScripts)
|
2014-05-05 18:20:40 -07:00
|
|
|
}
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
if (npm.config.get('json')) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output(JSON.stringify(d.scripts || {}, null, 2))
|
2015-03-06 02:57:32 -06:00
|
|
|
return cb(null, allScripts)
|
|
|
|
}
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
if (npm.config.get('parseable')) {
|
|
|
|
allScripts.forEach(function (script) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output(script + ':' + d.scripts[script])
|
2015-03-06 02:57:32 -06:00
|
|
|
})
|
|
|
|
return cb(null, allScripts)
|
2014-05-05 18:20:40 -07:00
|
|
|
}
|
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
var s = '\n '
|
|
|
|
var prefix = ' '
|
2015-03-06 02:57:32 -06:00
|
|
|
if (scripts.length) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output('Lifecycle scripts included in %s:', d.name)
|
2014-05-05 18:20:40 -07:00
|
|
|
}
|
2015-10-09 23:13:57 -07:00
|
|
|
scripts.forEach(function (script) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output(prefix + script + s + d.scripts[script])
|
2014-05-05 18:20:40 -07:00
|
|
|
})
|
2015-03-06 02:57:32 -06:00
|
|
|
if (!scripts.length && runScripts.length) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output('Scripts available in %s via `npm run-script`:', d.name)
|
2015-10-09 23:13:57 -07:00
|
|
|
} else if (runScripts.length) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output('\navailable via `npm run-script`:')
|
2015-03-06 02:57:32 -06:00
|
|
|
}
|
2015-10-09 23:13:57 -07:00
|
|
|
runScripts.forEach(function (script) {
|
2016-06-24 13:43:51 -07:00
|
|
|
output(prefix + script + s + d.scripts[script])
|
2015-03-06 02:57:32 -06:00
|
|
|
})
|
|
|
|
return cb(null, allScripts)
|
2014-05-05 18:20:40 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-09-24 14:41:07 -07:00
|
|
|
function run (pkg, wd, cmd, args, cb) {
|
2011-11-21 09:48:45 -08:00
|
|
|
if (!pkg.scripts) pkg.scripts = {}
|
2014-11-04 15:08:12 -08:00
|
|
|
|
|
|
|
var cmds
|
2015-10-09 23:13:57 -07:00
|
|
|
if (cmd === 'restart' && !pkg.scripts.restart) {
|
2014-11-04 15:08:12 -08:00
|
|
|
cmds = [
|
2015-10-09 23:13:57 -07:00
|
|
|
'prestop', 'stop', 'poststop',
|
|
|
|
'restart',
|
|
|
|
'prestart', 'start', 'poststart'
|
2014-11-04 15:08:12 -08:00
|
|
|
]
|
2011-11-21 09:48:45 -08:00
|
|
|
} else {
|
2019-04-05 15:17:30 -04:00
|
|
|
if (pkg.scripts[cmd] == null) {
|
2015-10-09 23:13:57 -07:00
|
|
|
if (cmd === 'test') {
|
|
|
|
pkg.scripts.test = 'echo \'Error: no test specified\''
|
|
|
|
} else if (cmd === 'env') {
|
2018-07-18 13:55:52 -07:00
|
|
|
if (isWindowsShell) {
|
2015-10-09 23:13:57 -07:00
|
|
|
log.verbose('run-script using default platform env: SET (Windows)')
|
|
|
|
pkg.scripts[cmd] = 'SET'
|
2015-01-17 00:50:09 -08:00
|
|
|
} else {
|
2015-10-09 23:13:57 -07:00
|
|
|
log.verbose('run-script using default platform env: env (Unix)')
|
|
|
|
pkg.scripts[cmd] = 'env'
|
2015-01-17 00:50:09 -08:00
|
|
|
}
|
2015-10-09 23:13:57 -07:00
|
|
|
} else if (npm.config.get('if-present')) {
|
|
|
|
return cb(null)
|
2015-01-08 14:37:26 -08:00
|
|
|
} else {
|
2018-07-18 13:55:52 -07:00
|
|
|
let suggestions = didYouMean(cmd, Object.keys(pkg.scripts))
|
|
|
|
suggestions = suggestions ? '\n' + suggestions : ''
|
|
|
|
return cb(new Error('missing script: ' + cmd + suggestions))
|
2015-01-08 14:37:26 -08:00
|
|
|
}
|
|
|
|
}
|
2011-11-21 09:48:45 -08:00
|
|
|
cmds = [cmd]
|
|
|
|
}
|
2014-11-04 15:08:12 -08:00
|
|
|
|
2011-11-21 09:48:45 -08:00
|
|
|
if (!cmd.match(/^(pre|post)/)) {
|
2015-10-09 23:13:57 -07:00
|
|
|
cmds = ['pre' + cmd].concat(cmds).concat('post' + cmd)
|
2011-11-21 09:48:45 -08:00
|
|
|
}
|
2014-11-04 15:08:12 -08:00
|
|
|
|
2015-10-09 23:13:57 -07:00
|
|
|
log.verbose('run-script', cmds)
|
2011-11-21 09:48:45 -08:00
|
|
|
chain(cmds.map(function (c) {
|
2014-09-24 14:41:07 -07:00
|
|
|
// pass cli arguments after -- to script.
|
2015-01-17 00:50:09 -08:00
|
|
|
if (pkg.scripts[c] && c === cmd) {
|
|
|
|
pkg.scripts[c] = pkg.scripts[c] + joinArgs(args)
|
|
|
|
}
|
2014-09-24 14:41:07 -07:00
|
|
|
|
2011-11-21 09:48:45 -08:00
|
|
|
// when running scripts explicitly, assume that they're trusted.
|
2017-10-26 22:35:25 -04:00
|
|
|
return [lifecycle, pkg, c, wd, { unsafePerm: true }]
|
2011-11-21 09:48:45 -08:00
|
|
|
}), cb)
|
|
|
|
}
|
2014-09-24 14:41:07 -07:00
|
|
|
|
|
|
|
// join arguments after '--' and pass them to script,
|
|
|
|
// handle special characters such as ', ", ' '.
|
|
|
|
function joinArgs (args) {
|
2015-10-09 23:13:57 -07:00
|
|
|
var joinedArgs = ''
|
|
|
|
args.forEach(function (arg) {
|
2015-04-10 05:56:01 -07:00
|
|
|
joinedArgs += ' "' + arg.replace(/"/g, '\\"') + '"'
|
2014-09-24 14:41:07 -07:00
|
|
|
})
|
|
|
|
return joinedArgs
|
|
|
|
}
|