UNPKG

4.2 kBJavaScriptView Raw
1
2module.exports = publish
3
4var npm = require("./npm.js")
5 , log = require("npmlog")
6 , tar = require("./utils/tar.js")
7 , path = require("path")
8 , readJson = require("read-package-json")
9 , fs = require("graceful-fs")
10 , lifecycle = require("./utils/lifecycle.js")
11 , chain = require("slide").chain
12 , Conf = require("npmconf").Conf
13 , RegClient = require("npm-registry-client")
14
15publish.usage = "npm publish <tarball>"
16 + "\nnpm publish <folder>"
17 + "\n\nPublishes '.' if no argument supplied"
18
19publish.completion = function (opts, cb) {
20 // publish can complete to a folder with a package.json
21 // or a tarball, or a tarball url.
22 // for now, not yet implemented.
23 return cb()
24}
25
26function publish (args, isRetry, cb) {
27 if (typeof cb !== "function") cb = isRetry, isRetry = false
28 if (args.length === 0) args = ["."]
29 if (args.length !== 1) return cb(publish.usage)
30
31 log.verbose("publish", args)
32 var arg = args[0]
33 // if it's a local folder, then run the prepublish there, first.
34 readJson(path.resolve(arg, "package.json"), function (er, data) {
35 er = needVersion(er, data)
36 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
37 // error is ok. could be publishing a url or tarball
38 // however, that means that we will not have automatically run
39 // the prepublish script, since that gets run when adding a folder
40 // to the cache.
41 if (er) return cacheAddPublish(arg, false, isRetry, cb)
42 cacheAddPublish(arg, true, isRetry, cb)
43 })
44}
45
46// didPre in this case means that we already ran the prepublish script,
47// and that the "dir" is an actual directory, and not something silly
48// like a tarball or name@version thing.
49// That means that we can run publish/postpublish in the dir, rather than
50// in the cache dir.
51function cacheAddPublish (dir, didPre, isRetry, cb) {
52 npm.commands.cache.add(dir, function (er, data) {
53 if (er) return cb(er)
54 log.silly("publish", data)
55 var cachedir = path.resolve( npm.cache
56 , data.name
57 , data.version
58 , "package" )
59 chain
60 ( [ !didPre && [lifecycle, data, "prepublish", cachedir]
61 , [publish_, dir, data, isRetry, cachedir]
62 , [lifecycle, data, "publish", didPre ? dir : cachedir]
63 , [lifecycle, data, "postpublish", didPre ? dir : cachedir] ]
64 , cb )
65 })
66}
67
68function publish_ (arg, data, isRetry, cachedir, cb) {
69 if (!data) return cb(new Error("no package.json file found"))
70
71 // check for publishConfig hash
72 var registry = npm.registry
73 if (data.publishConfig) {
74 var pubConf = new Conf(npm.config)
75 pubConf.save = npm.config.save.bind(npm.config)
76
77 // don't modify the actual publishConfig object, in case we have
78 // to set a login token or some other data.
79 pubConf.unshift(Object.keys(data.publishConfig).reduce(function (s, k) {
80 s[k] = data.publishConfig[k]
81 return s
82 }, {}))
83 registry = new RegClient(pubConf)
84 }
85
86 data._npmVersion = npm.version
87 data._npmUser = { name: npm.config.get("username")
88 , email: npm.config.get("email") }
89
90 delete data.modules
91 if (data.private) return cb(new Error
92 ("This package has been marked as private\n"
93 +"Remove the 'private' field from the package.json to publish it."))
94
95 var tarball = cachedir + ".tgz"
96 registry.publish(data, tarball, function (er) {
97 if (er && er.code === "EPUBLISHCONFLICT"
98 && npm.config.get("force") && !isRetry) {
99 log.warn("publish", "Forced publish over "+data._id)
100 return npm.commands.unpublish([data._id], function (er) {
101 // ignore errors. Use the force. Reach out with your feelings.
102 // but if it fails again, then report the first error.
103 publish([arg], er || true, cb)
104 })
105 }
106 // report the unpublish error if this was a retry and unpublish failed
107 if (er && isRetry && isRetry !== true) return cb(isRetry)
108 if (er) return cb(er)
109 console.log("+ " + data._id)
110 cb()
111 })
112}
113
114function needVersion(er, data) {
115 return er ? er
116 : (data && !data.version) ? new Error("No version provided")
117 : null
118}