UNPKG

4.28 kBJavaScriptView Raw
1
2module.exports = runScript
3
4var lifecycle = require("./utils/lifecycle.js")
5 , npm = require("./npm.js")
6 , path = require("path")
7 , readJson = require("read-package-json")
8 , log = require("npmlog")
9 , chain = require("slide").chain
10
11runScript.usage = "npm run-script <command> [-- <args>]"
12
13runScript.completion = function (opts, cb) {
14
15 // see if there's already a package specified.
16 var argv = opts.conf.argv.remain
17 , installedShallow = require("./utils/completion/installed-shallow.js")
18
19 if (argv.length >= 4) return cb()
20
21 if (argv.length === 3) {
22 // either specified a script locally, in which case, done,
23 // or a package, in which case, complete against its scripts
24 var json = path.join(npm.localPrefix, "package.json")
25 return readJson(json, function (er, d) {
26 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
27 if (er) d = {}
28 var scripts = Object.keys(d.scripts || {})
29 console.error("local scripts", scripts)
30 if (scripts.indexOf(argv[2]) !== -1) return cb()
31 // ok, try to find out which package it was, then
32 var pref = npm.config.get("global") ? npm.config.get("prefix")
33 : npm.localPrefix
34 var pkgDir = path.resolve( pref, "node_modules"
35 , argv[2], "package.json" )
36 readJson(pkgDir, function (er, d) {
37 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
38 if (er) d = {}
39 var scripts = Object.keys(d.scripts || {})
40 return cb(null, scripts)
41 })
42 })
43 }
44
45 // complete against the installed-shallow, and the pwd's scripts.
46 // but only packages that have scripts
47 var installed
48 , scripts
49 installedShallow(opts, function (d) {
50 return d.scripts
51 }, function (er, inst) {
52 installed = inst
53 next()
54 })
55
56 if (npm.config.get("global")) {
57 scripts = []
58 next()
59 }
60 else readJson(path.join(npm.localPrefix, "package.json"), function (er, d) {
61 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
62 d = d || {}
63 scripts = Object.keys(d.scripts || {})
64 next()
65 })
66
67 function next () {
68 if (!installed || !scripts) return
69
70 cb(null, scripts.concat(installed))
71 }
72}
73
74function runScript (args, cb) {
75 if (!args.length) return list(cb)
76
77 var pkgdir = npm.localPrefix
78 , cmd = args.shift()
79
80 readJson(path.resolve(pkgdir, "package.json"), function (er, d) {
81 if (er) return cb(er)
82 run(d, pkgdir, cmd, args, cb)
83 })
84}
85
86function list(cb) {
87 var json = path.join(npm.localPrefix, "package.json")
88 return readJson(json, function(er, d) {
89 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
90 if (er) d = {}
91 var scripts = Object.keys(d.scripts || {})
92
93 if (log.level === "silent") {
94 return cb(null, scripts)
95 }
96
97 if (npm.config.get("json")) {
98 console.log(JSON.stringify(d.scripts || {}, null, 2))
99 return cb(null, scripts)
100 }
101
102 var s = ":"
103 var prefix = ""
104 if (!npm.config.get("parseable")) {
105 s = "\n "
106 prefix = " "
107 console.log("Available scripts in the %s package:", d.name)
108 }
109 scripts.forEach(function(script) {
110 console.log(prefix + script + s + d.scripts[script])
111 })
112 return cb(null, scripts)
113 })
114}
115
116function run (pkg, wd, cmd, args, cb) {
117 if (!pkg.scripts) pkg.scripts = {}
118
119 var cmds
120 if (cmd === "restart") {
121 cmds = [
122 "prestop", "stop", "poststop",
123 "restart",
124 "prestart", "start", "poststart"
125 ]
126 } else {
127 cmds = [cmd]
128 }
129
130 if (!cmd.match(/^(pre|post)/)) {
131 cmds = ["pre"+cmd].concat(cmds).concat("post"+cmd)
132 }
133
134 log.verbose("run-script", cmds)
135 chain(cmds.map(function (c) {
136 // pass cli arguments after -- to script.
137 if (pkg.scripts[c] && c === cmd) pkg.scripts[c] = pkg.scripts[c] + joinArgs(args)
138
139 // when running scripts explicitly, assume that they're trusted.
140 return [lifecycle, pkg, c, wd, true]
141 }), cb)
142}
143
144// join arguments after '--' and pass them to script,
145// handle special characters such as ', ", ' '.
146function joinArgs (args) {
147 var joinedArgs = ""
148 args.forEach(function(arg) {
149 if (arg.match(/[ '"]/)) arg = '"' + arg.replace(/"/g, '\\"') + '"'
150 joinedArgs += " " + arg
151 })
152 return joinedArgs
153}