1 | # npm-registry
|
2 |
|
3 | To keep myself sane while working with The npm Registry I decided to write my
|
4 | own library to deal with all the incomplete, inconsistent and horrible data
|
5 | structures that are available in The npm Registry. NoSQL is nice and all, but
|
6 | that doesn't mean you should leave your data unmaintained. This library is never
|
7 | meant as a full replacement of the `npm-registry-client` which the `npm` bin
|
8 | file is using. Unless those API's and methods are so poorly implemented or
|
9 | designed that I get a mental breakdown, then yes, this will become a full and
|
10 | usable replacement of the above said module.
|
11 |
|
12 | This module is written with high availability in mind. The main reason behind
|
13 | this is that npm Inc. has added a lot of moving parts on top of the registry
|
14 | which frequently breaks. In order to combat this I've implemented automatic
|
15 | downgrading to multiple registries. If all other supplied registries fail to
|
16 | work an automatic exponential randomized back off algorithm kicks in place and
|
17 | retries the query once more. This functionality is all provided by the awesome
|
18 | [mana] package which provides core functionality for writing sane api-clients.
|
19 |
|
20 | ## Installation
|
21 |
|
22 | ```
|
23 | npm install --save npm-registry
|
24 | ```
|
25 |
|
26 | And that is all you need to type in your terminal in order to prevent becoming
|
27 | terminal. The `--save` tells `npm` to automatically add the package and latest
|
28 | version to your `package.json`.
|
29 |
|
30 | ## Getting started
|
31 |
|
32 | Now that you've installed the `npm-registry` module you can require and
|
33 | initialize it using:
|
34 |
|
35 | ```js
|
36 | 'use strict';
|
37 |
|
38 | var Registry = require('npm-registry');
|
39 |
|
40 | var npm = new Registry({ options });
|
41 | ```
|
42 |
|
43 | As seen in the example above, the `Registry` constructor allows an `Object` with
|
44 | options to customize the npm registry client. The following options are supported:
|
45 |
|
46 | - `registry` The URL of the npm registry. Defaults to Nodejitsu's mirror.
|
47 | - `stats` URL of the download stats service. Defaults to npm's API server.
|
48 | - `mirrors` Array of mirrors to use when a registry is down.
|
49 | - `maxdelay` Maximum delay for exponential back off.
|
50 | - `mindelay` Minimum delay for exponential back off.
|
51 | - `githulk` Reference to a pre-configured [GitHulk] instance.
|
52 | - `retries` The amount of retries we should do before giving up.
|
53 | - `factor` Exponential backoff factor.
|
54 | - `authorization` Optional authorization header for authorized requests.
|
55 | - `user,password` Optional user/password for authorized requests.
|
56 |
|
57 | The fully configured npm registry client can then be used to access the various
|
58 | of API endpoints using:
|
59 |
|
60 | ```js
|
61 | //
|
62 | // npm.<endpoint>.<method>(<arg>, <callback>);
|
63 | //
|
64 | npm.packages.get('npm-registry', function (err, data) {
|
65 | ..
|
66 | });
|
67 | ```
|
68 |
|
69 | The following endpoints are available:
|
70 |
|
71 | ### Packages
|
72 |
|
73 | The `.packages` endpoints allows you to retrieve detailed information about npm
|
74 | packages. The following methods are implemented:
|
75 |
|
76 | - [npm.packages.get](#npmpackagesget)
|
77 | - [npm.packages.details](#npmpackagesdetails)
|
78 | - [npm.packages.depended](#npmpackagesdepended)
|
79 | - [npm.packages.starred](#npmpackagesstarred)
|
80 | - [npm.packages.keyword](#npmpackageskeyword)
|
81 | - [npm.packages.releases](#npmpackagesreleases)
|
82 | - [npm.packages.release](#npmpackagesrelease)
|
83 | - [npm.packages.range](#npmpackagesrange)
|
84 |
|
85 | #### npm.packages.get
|
86 |
|
87 | Get information from the npm package. If the name contains an `@` char we assume
|
88 | that the user wants to get a specific version instead.
|
89 |
|
90 | Example: **primus@0.1.1 would retrieve primus version 0.1.1**
|
91 |
|
92 | ```js
|
93 | npm.packages.get('primus', function (err, data) {
|
94 |
|
95 | });
|
96 | ```
|
97 |
|
98 | #### npm.packages.details
|
99 |
|
100 | Retrieve additional details for the package information. This a lot slower than
|
101 | a simple `.get` but much more detailed and accurate as it uses custom parsers
|
102 | for accurate licensing information. Which could require a fair amount of npm and
|
103 | github lookups.
|
104 |
|
105 | ```js
|
106 | npm.packages.details('memcached', function (err, data) {
|
107 |
|
108 | });
|
109 | ```
|
110 |
|
111 | #### npm.packages.depended
|
112 |
|
113 | Get all packages that are depended upon a given package name.
|
114 |
|
115 | ```js
|
116 | npm.packages.depended('eventemitter3', function (err, depended) {
|
117 |
|
118 | });
|
119 | ```
|
120 |
|
121 | #### npm.packages.starred
|
122 |
|
123 | Find out which users have starred the given package.
|
124 |
|
125 | ```js
|
126 | npm.packages.starred('npm-registry', function (err, starred) {
|
127 |
|
128 | });
|
129 | ```
|
130 |
|
131 | #### npm.packages.keyword
|
132 |
|
133 | Find all packages that matches the giving keywords.
|
134 |
|
135 | ```js
|
136 | npm.packages.keyword('primus');
|
137 | ```
|
138 |
|
139 | #### npm.packages.releases
|
140 |
|
141 | Retrieve all release specific information for the given package name. Please
|
142 | note that this uses the `npm.packages.details` call under the hood to provide
|
143 | more detailed information but it will therefor also take longer.
|
144 |
|
145 | ```js
|
146 | npm.packages.releases('bigpipe', function (err, releases) {
|
147 |
|
148 | });
|
149 | ```
|
150 |
|
151 | #### npm.packages.release
|
152 |
|
153 | Get a specific release of a package. Please note that this uses the
|
154 | `npm.packages.details` call under the hood to provide more detailed information
|
155 | but it will therefor also take longer.
|
156 |
|
157 | ```js
|
158 | npm.packages.release('npm-registry', '0.0.2', function (err, release) {
|
159 |
|
160 | });
|
161 | ```
|
162 |
|
163 | #### npm.packages.range
|
164 |
|
165 | Get a release that is satisfying a given semver range. Please note that this
|
166 | uses the `npm.packages.details` call under the hood to provide more detailed
|
167 | information but it will therefor also take longer.
|
168 |
|
169 | ```js
|
170 | npm.packages.release('npm-registry', '^0.1.2', function (err, release) {
|
171 |
|
172 | });
|
173 | ```
|
174 |
|
175 | ### Users
|
176 |
|
177 | The `.users` endpoint allows you to retrieve detailed information about a given
|
178 | npm account. The following methods are implemented:
|
179 |
|
180 | - [npm.users.add](#npmusersadd)
|
181 | - [npm.users.create](#npmuserscreate)
|
182 | - [npm.users.update](#npmusersupdate)
|
183 | - [npm.users.list](#npmuserslist)
|
184 | - [npm.users.starred](#npmusersstarred)
|
185 | - [npm.users.get](#npmusersget)
|
186 | - [npm.users.sync](#npmuserssync)
|
187 |
|
188 | #### npm.users.add
|
189 |
|
190 | Add a user as maintainer of a package.
|
191 |
|
192 | ```js
|
193 | npm.users.add('foobar', 'npm-registry', function (err) {
|
194 |
|
195 | });
|
196 | ```
|
197 |
|
198 | #### npm.users.create
|
199 |
|
200 | Create a new npm account.
|
201 |
|
202 | ```js
|
203 | npm.users.create('foobar', 'foo@bar.com', 'secretpassword', function (err) {
|
204 |
|
205 | });
|
206 | ```
|
207 |
|
208 | #### npm.users.update
|
209 |
|
210 | Update the users.
|
211 |
|
212 | ```js
|
213 | npm.users.update('foobar', {
|
214 | twitter: 'foobar',
|
215 | email: 'foo@foobar.bar'
|
216 | }, function (err) {
|
217 |
|
218 | });
|
219 | ```
|
220 |
|
221 | #### npm.users.list
|
222 |
|
223 | List all packages that the user maintains.
|
224 |
|
225 | ```js
|
226 | npm.users.list('foobar', function (err, modules) {
|
227 |
|
228 | });
|
229 | ```
|
230 |
|
231 | #### npm.users.starred
|
232 |
|
233 | Get all packages that the user has starred.
|
234 |
|
235 | ```js
|
236 | npm.users.starred('foobar', function (err, modules) {
|
237 |
|
238 | });
|
239 | ```
|
240 |
|
241 | #### npm.users.get
|
242 |
|
243 | Get profile information for a given user.
|
244 |
|
245 | ```js
|
246 | npm.users.get('foobar', function (err) {
|
247 |
|
248 | });
|
249 | ```
|
250 |
|
251 | #### npm.users.sync
|
252 |
|
253 | Sync ownership of npm modules with another account. This is useful if you have
|
254 | one base owner of modules like a corporate account and you want to on-board a
|
255 | new user.
|
256 |
|
257 | ```js
|
258 | npm.users.sync('source-account', 'foobar', function (err) {
|
259 |
|
260 | });
|
261 | ```
|
262 |
|
263 | ### Downloads
|
264 |
|
265 | The `.downloads` endpoint allows you to retrieve download stats for a given
|
266 | package. The following methods are implemented:
|
267 |
|
268 | - [npm.downloads.totals](#npmdownloadstotals)
|
269 | - [npm.downloads.range](#npmdownloadsrange)
|
270 |
|
271 | #### npm.downloads.totals
|
272 |
|
273 | Get the total amount of downloads for a given period. If no package name has
|
274 | been supplied the total of all packages will be returned. The following date ranges
|
275 | are accepted by the stats server.
|
276 |
|
277 | - All packages, last day:
|
278 | - last day: `last-day`
|
279 | - specific date: `2014-02-01`
|
280 | - last week: `last-week
|
281 | - range of date (30 days max): `2014-02-01:2014-02-08`
|
282 | - last month: `last-month`A
|
283 | - specific month: `2014-01-01:2014-01-31`
|
284 |
|
285 | ```js
|
286 | npm.downloads.totals('last-week', 'npm-registry', function (err, stats) {
|
287 |
|
288 | });
|
289 | ```
|
290 |
|
291 | #### npm.downloads.range
|
292 |
|
293 | Same as above, but it doesn't get the total/summary of the downloads but an array
|
294 | with the downloads per day. The same date ranges are allowed and if no package name
|
295 | is supplied, all packages is assumed.
|
296 |
|
297 | ```js
|
298 | npm.downloads.range('last-week', 'npm-registry', function (err, stats) {
|
299 |
|
300 | });
|
301 | ```
|
302 |
|
303 | ## Normalization
|
304 |
|
305 | As the internal data structure is do damn awkward and unmaintained in npm we
|
306 | need to normalize the data structures before we can even try to use it. While
|
307 | this normalization is part automatically done for you internally there might be
|
308 | use cases where you want to manually normalize a given dataset. The normalize
|
309 | module can be required directly using:
|
310 |
|
311 | ```js
|
312 | var normalize = require('npmjs/normalize');
|
313 | ```
|
314 |
|
315 | The `normalize` variable now contains two different functions, `users` and
|
316 | `packages`. As you might have guessed, these functions normalize different data
|
317 | structures. The function accepts a simple single argument which is the data
|
318 | object that you receive from the npm registry endpoints.
|
319 |
|
320 | ```js
|
321 | data = normalize.packages(data);
|
322 | ```
|
323 |
|
324 | ## License
|
325 |
|
326 | MIT
|
327 |
|
328 | [mana]: http://github.com/3rd-Eden/mana
|
329 | [Githulk]: http://github.com/3rd-Eden/githulk
|