summaryrefslogtreecommitdiff
path: root/deps/npm/lib/run-script.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/run-script.js')
-rw-r--r--deps/npm/lib/run-script.js272
1 files changed, 117 insertions, 155 deletions
diff --git a/deps/npm/lib/run-script.js b/deps/npm/lib/run-script.js
index 476591c051..90f11270c6 100644
--- a/deps/npm/lib/run-script.js
+++ b/deps/npm/lib/run-script.js
@@ -1,72 +1,92 @@
-module.exports = runScript
-
-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
-var usage = require('./utils/usage')
-var output = require('./utils/output.js')
-var didYouMean = require('./utils/did-you-mean')
-var isWindowsShell = require('./utils/is-windows-shell.js')
-
-runScript.usage = usage(
+const run = require('@npmcli/run-script')
+const npm = require('./npm.js')
+const readJson = require('read-package-json-fast')
+const { resolve } = require('path')
+const output = require('./utils/output.js')
+const log = require('npmlog')
+const usageUtil = require('./utils/usage')
+const didYouMean = require('./utils/did-you-mean')
+const isWindowsShell = require('./utils/is-windows-shell.js')
+
+const usage = usageUtil(
'run-script',
- 'npm run-script <command> [-- <args>...]'
+ 'npm run-script <command> [-- <args>]'
)
-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
- var json = path.join(npm.localPrefix, 'package.json')
- return readJson(json, function (er, d) {
- if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
- if (er) d = {}
- var scripts = Object.keys(d.scripts || {})
- console.error('local scripts', scripts)
- if (scripts.indexOf(argv[2]) !== -1) return cb()
- // ok, try to find out which package it was, then
- var pref = npm.config.get('global') ? npm.config.get('prefix')
- : npm.localPrefix
- var pkgDir = path.resolve(pref, 'node_modules', argv[2], 'package.json')
- readJson(pkgDir, function (er, d) {
- if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
- if (er) d = {}
- var scripts = Object.keys(d.scripts || {})
- return cb(null, scripts)
- })
- })
+const completion = async (opts, cb) => {
+ const argv = opts.conf.argv.remain
+ if (argv.length === 2) {
+ // find the script name
+ const json = resolve(npm.localPrefix, 'package.json')
+ const { scripts = {} } = await readJson(json).catch(er => ({}))
+ return cb(null, Object.keys(scripts))
}
+ // otherwise nothing to do, just let the system handle it
+ return cb()
+}
- readJson(path.join(npm.localPrefix, 'package.json'), function (er, d) {
- if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
- d = d || {}
- cb(null, Object.keys(d.scripts || {}))
- })
+const cmd = (args, cb) => {
+ const fn = args.length ? runScript : list
+ return fn(args).then(() => cb()).catch(cb)
}
-function runScript (args, cb) {
- if (!args.length) return list(cb)
+const runScript = async (args) => {
+ const path = npm.localPrefix
+ const event = args.shift()
+ const { scriptShell } = npm.flatOptions
+
+ const pkg = await readJson(`${path}/package.json`)
+ const { scripts = {} } = pkg
+
+ if (event === 'restart' && !scripts.restart) {
+ scripts.restart = 'npm stop --if-present && npm start'
+ } else if (event === 'env') {
+ scripts.env = isWindowsShell ? 'SET' : 'env'
+ }
+ pkg.scripts = scripts
+
+ if (!scripts[event]) {
+ if (npm.config.get('if-present')) {
+ return
+ }
+ const suggestions = didYouMean(event, Object.keys(scripts))
+ throw new Error(`missing script: ${event}${
+ suggestions ? `\n${suggestions}` : ''}`)
+ }
+
+ // positional args only added to the main event, not pre/post
+ const events = [[event, args]]
+ if (!npm.flatOptions.ignoreScripts) {
+ if (scripts[`pre${event}`]) {
+ events.unshift([`pre${event}`, []])
+ }
+ if (scripts[`post${event}`]) {
+ events.push([`post${event}`, []])
+ }
+ }
- var pkgdir = npm.localPrefix
- var cmd = args.shift()
+ const opts = {
+ path,
+ args,
+ scriptShell,
+ stdio: log.level === 'silent' ? 'pipe' : 'inherit',
+ stdioString: true,
+ pkg
+ }
- readJson(path.resolve(pkgdir, 'package.json'), function (er, d) {
- if (er) return cb(er)
- run(d, pkgdir, cmd, args, cb)
- })
+ for (const [event, args] of events) {
+ await run({
+ ...opts,
+ event,
+ args
+ })
+ }
}
-function list (cb) {
- var json = path.join(npm.localPrefix, 'package.json')
- var cmdList = [
+const list = async () => {
+ const path = npm.localPrefix
+ const { scripts, name } = await readJson(`${path}/package.json`)
+ const cmdList = [
'publish',
'install',
'uninstall',
@@ -75,111 +95,53 @@ function list (cb) {
'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)
- if (er) d = {}
- 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)
- })
-
- if (log.level === 'silent') {
- return cb(null, allScripts)
- }
+ ].reduce((l, p) => l.concat(['pre' + p, p, 'post' + p]), [])
- if (npm.config.get('json')) {
- output(JSON.stringify(d.scripts || {}, null, 2))
- return cb(null, allScripts)
- }
+ if (!scripts) {
+ return []
+ }
- if (npm.config.get('parseable')) {
- allScripts.forEach(function (script) {
- output(script + ':' + d.scripts[script])
- })
- return cb(null, allScripts)
- }
+ const allScripts = Object.keys(scripts)
+ if (log.level === 'silent') {
+ return allScripts
+ }
- var s = '\n '
- var prefix = ' '
- if (scripts.length) {
- output('Lifecycle scripts included in %s:', d.name)
- }
- scripts.forEach(function (script) {
- output(prefix + script + s + d.scripts[script])
- })
- if (!scripts.length && runScripts.length) {
- output('Scripts available in %s via `npm run-script`:', d.name)
- } else if (runScripts.length) {
- output('\navailable via `npm run-script`:')
- }
- runScripts.forEach(function (script) {
- output(prefix + script + s + d.scripts[script])
- })
- return cb(null, allScripts)
- })
-}
+ if (npm.flatOptions.json) {
+ output(JSON.stringify(scripts, null, 2))
+ return allScripts
+ }
-function run (pkg, wd, cmd, args, cb) {
- if (!pkg.scripts) pkg.scripts = {}
-
- var cmds
- if (cmd === 'restart' && !pkg.scripts.restart) {
- cmds = [
- 'prestop', 'stop', 'poststop',
- 'restart',
- 'prestart', 'start', 'poststart'
- ]
- } else {
- if (pkg.scripts[cmd] == null) {
- if (cmd === 'test') {
- pkg.scripts.test = 'echo \'Error: no test specified\''
- } else if (cmd === 'env') {
- if (isWindowsShell) {
- log.verbose('run-script using default platform env: SET (Windows)')
- pkg.scripts[cmd] = 'SET'
- } else {
- log.verbose('run-script using default platform env: env (Unix)')
- pkg.scripts[cmd] = 'env'
- }
- } else if (npm.config.get('if-present')) {
- return cb(null)
- } else {
- let suggestions = didYouMean(cmd, Object.keys(pkg.scripts))
- suggestions = suggestions ? '\n' + suggestions : ''
- return cb(new Error('missing script: ' + cmd + suggestions))
- }
+ if (npm.flatOptions.parseable) {
+ for (const [script, cmd] of Object.entries(scripts)) {
+ output(`${script}:${cmd}`)
}
- cmds = [cmd]
+ return allScripts
}
- if (!cmd.match(/^(pre|post)/)) {
- cmds = ['pre' + cmd].concat(cmds).concat('post' + cmd)
+ const indent = '\n '
+ const prefix = ' '
+ const cmds = []
+ const runScripts = []
+ for (const script of allScripts) {
+ const list = cmdList.includes(script) ? cmds : runScripts
+ list.push(script)
}
- log.verbose('run-script', cmds)
- chain(cmds.map(function (c) {
- // pass cli arguments after -- to script.
- if (pkg.scripts[c] && c === cmd) {
- pkg.scripts[c] = pkg.scripts[c] + joinArgs(args)
- }
-
- // when running scripts explicitly, assume that they're trusted.
- return [lifecycle, pkg, c, wd, { unsafePerm: true }]
- }), cb)
+ if (cmds.length) {
+ output(`Lifecycle scripts included in ${name}:`)
+ }
+ for (const script of cmds) {
+ output(prefix + script + indent + scripts[script])
+ }
+ 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])
+ }
+ return allScripts
}
-// join arguments after '--' and pass them to script,
-// handle special characters such as ', ", ' '.
-function joinArgs (args) {
- var joinedArgs = ''
- args.forEach(function (arg) {
- joinedArgs += ' "' + arg.replace(/"/g, '\\"') + '"'
- })
- return joinedArgs
-}
+module.exports = Object.assign(cmd, { completion, usage })