UNPKG

7.56 kBJavaScriptView Raw
1module.exports = owner
2
3owner.usage = "npm owner add <username> <pkg>"
4 + "\nnpm owner rm <username> <pkg>"
5 + "\nnpm owner ls <pkg>"
6
7var npm = require("./npm.js")
8 , log = require("npmlog")
9 , mapToRegistry = require("./utils/map-to-registry.js")
10 , readLocalPkg = require("./utils/read-local-package.js")
11
12owner.completion = function (opts, cb) {
13 var argv = opts.conf.argv.remain
14 if (argv.length > 4) return cb()
15 if (argv.length <= 2) {
16 var subs = ["add", "rm"]
17 if (opts.partialWord === "l") subs.push("ls")
18 else subs.push("ls", "list")
19 return cb(null, subs)
20 }
21
22 npm.commands.whoami([], true, function (er, username) {
23 if (er) return cb()
24
25 var un = encodeURIComponent(username)
26 var byUser, theUser
27 switch (argv[2]) {
28 case "ls":
29 if (argv.length > 3) return cb()
30 return mapToRegistry("-/short", npm.config, function (er, uri, auth) {
31 if (er) return cb(er)
32
33 npm.registry.get(uri, { auth : auth }, cb)
34 })
35
36 case "rm":
37 if (argv.length > 3) {
38 theUser = encodeURIComponent(argv[3])
39 byUser = "-/by-user/" + theUser + "|" + un
40 return mapToRegistry(byUser, npm.config, function (er, uri, auth) {
41 if (er) return cb(er)
42
43 console.error(uri)
44 npm.registry.get(uri, { auth : auth }, function (er, d) {
45 if (er) return cb(er)
46 // return the intersection
47 return cb(null, d[theUser].filter(function (p) {
48 // kludge for server adminery.
49 return un === "isaacs" || d[un].indexOf(p) === -1
50 }))
51 })
52 })
53 }
54 // else fallthrough
55 case "add":
56 if (argv.length > 3) {
57 theUser = encodeURIComponent(argv[3])
58 byUser = "-/by-user/" + theUser + "|" + un
59 return mapToRegistry(byUser, npm.config, function (er, uri, auth) {
60 if (er) return cb(er)
61
62 console.error(uri)
63 npm.registry.get(uri, { auth : auth }, function (er, d) {
64 console.error(uri, er || d)
65 // return mine that they're not already on.
66 if (er) return cb(er)
67 var mine = d[un] || []
68 , theirs = d[theUser] || []
69 return cb(null, mine.filter(function (p) {
70 return theirs.indexOf(p) === -1
71 }))
72 })
73 })
74 }
75 // just list all users who aren't me.
76 return mapToRegistry("-/users", npm.config, function (er, uri, auth) {
77 if (er) return cb(er)
78
79 npm.registry.get(uri, { auth : auth }, function (er, list) {
80 if (er) return cb()
81 return cb(null, Object.keys(list).filter(function (n) {
82 return n !== un
83 }))
84 })
85 })
86
87 default:
88 return cb()
89 }
90 })
91}
92
93function owner (args, cb) {
94 var action = args.shift()
95 switch (action) {
96 case "ls": case "list": return ls(args[0], cb)
97 case "add": return add(args[0], args[1], cb)
98 case "rm": case "remove": return rm(args[0], args[1], cb)
99 default: return unknown(action, cb)
100 }
101}
102
103function ls (pkg, cb) {
104 if (!pkg) return readLocalPkg(function (er, pkg) {
105 if (er) return cb(er)
106 if (!pkg) return cb(owner.usage)
107 ls(pkg, cb)
108 })
109
110 mapToRegistry(pkg, npm.config, function (er, uri, auth) {
111 if (er) return cb(er)
112
113 npm.registry.get(uri, { auth : auth }, function (er, data) {
114 var msg = ""
115 if (er) {
116 log.error("owner ls", "Couldn't get owner data", pkg)
117 return cb(er)
118 }
119 var owners = data.maintainers
120 if (!owners || !owners.length) msg = "admin party!"
121 else msg = owners.map(function (o) {
122 return o.name + " <" + o.email + ">"
123 }).join("\n")
124 console.log(msg)
125 cb(er, owners)
126 })
127 })
128}
129
130function add (user, pkg, cb) {
131 if (!user) return cb(owner.usage)
132 if (!pkg) return readLocalPkg(function (er, pkg) {
133 if (er) return cb(er)
134 if (!pkg) return cb(new Error(owner.usage))
135 add(user, pkg, cb)
136 })
137
138 log.verbose("owner add", "%s to %s", user, pkg)
139 mutate(pkg, user, function (u, owners) {
140 if (!owners) owners = []
141 for (var i = 0, l = owners.length; i < l; i ++) {
142 var o = owners[i]
143 if (o.name === u.name) {
144 log.info( "owner add"
145 , "Already a package owner: " + o.name + " <" + o.email + ">")
146 return false
147 }
148 }
149 owners.push(u)
150 return owners
151 }, cb)
152}
153
154function rm (user, pkg, cb) {
155 if (!pkg) return readLocalPkg(function (er, pkg) {
156 if (er) return cb(er)
157 if (!pkg) return cb(new Error(owner.usage))
158 rm(user, pkg, cb)
159 })
160
161 log.verbose("owner rm", "%s from %s", user, pkg)
162 mutate(pkg, user, function (u, owners) {
163 var found = false
164 , m = owners.filter(function (o) {
165 var match = (o.name === user)
166 found = found || match
167 return !match
168 })
169 if (!found) {
170 log.info("owner rm", "Not a package owner: " + user)
171 return false
172 }
173 if (!m.length) return new Error(
174 "Cannot remove all owners of a package. Add someone else first.")
175 return m
176 }, cb)
177}
178
179function mutate (pkg, user, mutation, cb) {
180 if (user) {
181 var byUser = "-/user/org.couchdb.user:" + user
182 mapToRegistry(byUser, npm.config, function (er, uri, auth) {
183 if (er) return cb(er)
184
185 npm.registry.get(uri, { auth : auth }, mutate_)
186 })
187 } else {
188 mutate_(null, null)
189 }
190
191 function mutate_ (er, u) {
192 if (!er && user && (!u || u.error)) er = new Error(
193 "Couldn't get user data for " + user + ": " + JSON.stringify(u))
194
195 if (er) {
196 log.error("owner mutate", "Error getting user data for %s", user)
197 return cb(er)
198 }
199
200 if (u) u = { "name" : u.name, "email" : u.email }
201 mapToRegistry(pkg, npm.config, function (er, uri, auth) {
202 if (er) return cb(er)
203
204 npm.registry.get(uri, { auth : auth }, function (er, data) {
205 if (er) {
206 log.error("owner mutate", "Error getting package data for %s", pkg)
207 return cb(er)
208 }
209
210 // save the number of maintainers before mutation so that we can figure
211 // out if maintainers were added or removed
212 var beforeMutation = data.maintainers.length
213
214 var m = mutation(u, data.maintainers)
215 if (!m) return cb() // handled
216 if (m instanceof Error) return cb(m) // error
217
218 data = {
219 _id : data._id,
220 _rev : data._rev,
221 maintainers : m
222 }
223 var dataPath = pkg.replace("/", "%2f") + "/-rev/" + data._rev
224 mapToRegistry(dataPath, npm.config, function (er, uri, auth) {
225 if (er) return cb(er)
226
227 var params = {
228 method : "PUT",
229 body : data,
230 auth : auth
231 }
232 npm.registry.request(uri, params, function (er, data) {
233 if (!er && data.error) {
234 er = new Error("Failed to update package metadata: "+JSON.stringify(data))
235 }
236
237 if (er) {
238 log.error("owner mutate", "Failed to update package metadata")
239 }
240 else if (m.length > beforeMutation) {
241 console.log("+ %s (%s)", user, pkg)
242 }
243 else if (m.length < beforeMutation) {
244 console.log("- %s (%s)", user, pkg)
245 }
246
247 cb(er, data)
248 })
249 })
250 })
251 })
252 }
253}
254
255function unknown (action, cb) {
256 cb("Usage: \n" + owner.usage)
257}