+++ /dev/null
-language: node_js
-before_install: "make &>out || cat out; rm out"
-node_js:
- - 0.8
Kei Son <heyacct@gmail.com>
Nicolas Morel <marsup@gmail.com>
Mark Dube <markisdee@gmail.com>
+Maxim Bogushevich <boga1@mail.ru>
+Justin Beckwith <justbe@microsoft.com>
--- /dev/null
+npm-dedupe(1) -- Reduce duplication
+===================================
+
+## SYNOPSIS
+
+ npm dedupe [package names...]
+
+## DESCRIPTION
+
+Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages.
+
+For example, consider this dependency graph:
+
+ a
+ +-- b <-- depends on c@1.0.x
+ | `-- c@1.0.3
+ `-- d <-- depends on c@~1.0.9
+ `-- c@1.0.10
+
+In this case, `npm-dedupe(1)` will transform the tree to:
+
+ a
+ +-- b
+ +-- d
+ `-- c@1.0.10
+
+Because of the hierarchical nature of node's module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree.
+
+If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted.
+
+If no suitable version can be found, then a warning is printed, and
+nothing is done.
+
+If any arguments are supplied, then they are filters, and only the
+named packages will be touched.
+
+Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry.
+
+This feature is experimental, and may change in future versions.
+
+## SEE ALSO
+
+* npm-ls(1)
+* npm-update(1)
+* npm-install(1)
Manage the npm configuration file
+## npm-dedupe(1)
+
+ Reduce duplication
+
## npm-deprecate(1)
Deprecate a version of a package
<p>This function should not be used programmatically. Instead, just refer
to the <code>npm.bin</code> member.</p>
</div>
-<p id="footer">bin — npm@1.1.49</p>
+<p id="footer">bin — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This command will launch a browser, so this command may not be the most
friendly for programmatic use.</p>
</div>
-<p id="footer">bugs — npm@1.1.49</p>
+<p id="footer">bugs — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer">commands — npm@1.1.49</p>
+<p id="footer">commands — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/npm.html">npm(3)</a></li></ul>
</div>
-<p id="footer">config — npm@1.1.49</p>
+<p id="footer">config — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/publish.html">publish(3)</a></li><li><a href="../api/unpublish.html">unpublish(3)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">deprecate — npm@1.1.49</p>
+<p id="footer">deprecate — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This command will launch a browser, so this command may not be the most
friendly for programmatic use.</p>
</div>
-<p id="footer">docs — npm@1.1.49</p>
+<p id="footer">docs — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Since this command opens an editor in a new process, be careful about where
and how this is used.</p>
</div>
-<p id="footer">edit — npm@1.1.49</p>
+<p id="footer">edit — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The first element in the 'args' parameter must be a package name. After that is the optional command, which can be any number of strings. All of the strings will be combined into one, space-delimited command.</p>
</div>
-<p id="footer">explore — npm@1.1.49</p>
+<p id="footer">explore — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The silent parameter is not neccessary not used, but it may in the future.</p>
</div>
-<p id="footer">help-search — npm@1.1.49</p>
+<p id="footer">help-search — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p><a href="../doc/json.html">json(1)</a></p>
</div>
-<p id="footer">init — npm@1.1.49</p>
+<p id="footer">init — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when all packages have been
installed or when an error has been encountered.</p>
</div>
-<p id="footer">install — npm@1.1.49</p>
+<p id="footer">install — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Now, any changes to the redis package will be reflected in
the package in the current working directory</p>
</div>
-<p id="footer">link — npm@1.1.49</p>
+<p id="footer">link — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>For a list of all the available command-line configs, see <code>npm help config</code></p>
</div>
-<p id="footer">load — npm@1.1.49</p>
+<p id="footer">load — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
This means that if a submodule a same dependency as a parent module, then the
dependency will only be output once.</p>
</div>
-<p id="footer">ls — npm@1.1.49</p>
+<p id="footer">ls — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<h2 id="VERSION">VERSION</h2>
-<p>1.1.49</p>
+<p>1.1.55</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<pre><code>var cmd = npm.deref("unp") // cmd === "unpublish"</code></pre>
</div>
-<p id="footer">npm — npm@1.1.49</p>
+<p id="footer">npm — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If the 'packages' parameter is left out, npm will check all packages.</p>
</div>
-<p id="footer">outdated — npm@1.1.49</p>
+<p id="footer">outdated — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/publish.html">publish(3)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">owner — npm@1.1.49</p>
+<p id="footer">owner — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If no arguments are supplied, then npm packs the current package folder.</p>
</div>
-<p id="footer">pack — npm@1.1.49</p>
+<p id="footer">pack — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically</p>
</div>
-<p id="footer">prefix — npm@1.1.49</p>
+<p id="footer">prefix — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Extraneous packages are packages that are not listed on the parent
package's dependencies list.</p>
</div>
-<p id="footer">prune — npm@1.1.49</p>
+<p id="footer">prune — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../api/owner.html">owner(3)</a></li></ul>
</div>
-<p id="footer">publish — npm@1.1.49</p>
+<p id="footer">publish — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>See <code>npm help build</code></p>
</div>
-<p id="footer">rebuild — npm@1.1.49</p>
+<p id="footer">rebuild — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../api/start.html">start(3)</a></li><li><a href="../api/stop.html">stop(3)</a></li></ul>
</div>
-<p id="footer">restart — npm@1.1.49</p>
+<p id="footer">restart — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically.</p>
</div>
-<p id="footer">root — npm@1.1.49</p>
+<p id="footer">root — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../api/test.html">test(3)</a></li><li><a href="../api/start.html">start(3)</a></li><li><a href="../api/restart.html">restart(3)</a></li><li><a href="../api/stop.html">stop(3)</a></li></ul>
</div>
-<p id="footer">run-script — npm@1.1.49</p>
+<p id="footer">run-script — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
and doesn't try to read your mind (it doesn't do any verb tense matching or the
like).</p>
</div>
-<p id="footer">search — npm@1.1.49</p>
+<p id="footer">search — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when the shrinkwrap has
been saved.</p>
</div>
-<p id="footer">shrinkwrap — npm@1.1.49</p>
+<p id="footer">shrinkwrap — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run tests on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">start — npm@1.1.49</p>
+<p id="footer">start — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run stop on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">stop — npm@1.1.49</p>
+<p id="footer">stop — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li>npm help json</li><li>git help submodule</li></ul>
</div>
-<p id="footer">submodule — npm@1.1.49</p>
+<p id="footer">submodule — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
used. For more information about how to set this config, check
<code>man 3 npm-config</code> for programmatic usage or <code>man npm-config</code> for cli usage.</p>
</div>
-<p id="footer">tag — npm@1.1.49</p>
+<p id="footer">tag — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>npm can run tests on multiple packages. Just specify multiple packages
in the <code>packages</code> parameter.</p>
</div>
-<p id="footer">test — npm@1.1.49</p>
+<p id="footer">test — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>Finally, 'callback' is a function that will be called when all packages have been
uninstalled or when an error has been encountered.</p>
</div>
-<p id="footer">uninstall — npm@1.1.49</p>
+<p id="footer">uninstall — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>If no version is specified, or if all versions are removed then
the root package entry is removed from the registry entirely.</p>
</div>
-<p id="footer">unpublish — npm@1.1.49</p>
+<p id="footer">unpublish — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>The 'packages' argument is an array of packages to update. The 'callback' parameter will be called when done or when an error occurs.</p>
</div>
-<p id="footer">update — npm@1.1.49</p>
+<p id="footer">update — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
parameter. The difference, however, is this function will fail if it does
not have exactly one element. The only element should be a version number.</p>
</div>
-<p id="footer">version — npm@1.1.49</p>
+<p id="footer">version — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>corresponding to the list of fields selected.</p>
</div>
-<p id="footer">view — npm@1.1.49</p>
+<p id="footer">view — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p>This function is not useful programmatically</p>
</div>
-<p id="footer">whoami — npm@1.1.49</p>
+<p id="footer">whoami — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer"><a href="../doc/README.html">README</a> — npm@1.1.49</p>
+<p id="footer"><a href="../doc/README.html">README</a> — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li><li><a href="../doc/whoami.html">whoami(1)</a></li></ul>
</div>
-<p id="footer">adduser — npm@1.1.49</p>
+<p id="footer">adduser — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/prefix.html">prefix(1)</a></li><li><a href="../doc/root.html">root(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">bin — npm@1.1.49</p>
+<p id="footer">bin — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/docs.html">docs(1)</a></li><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">bugs — npm@1.1.49</p>
+<p id="footer">bugs — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">build — npm@1.1.49</p>
+<p id="footer">build — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">bundle — npm@1.1.49</p>
+<p id="footer">bundle — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/pack.html">pack(1)</a></li></ul>
</div>
-<p id="footer">cache — npm@1.1.49</p>
+<p id="footer">cache — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li></ul>
</div>
-<p id="footer">changelog — npm@1.1.49</p>
+<p id="footer">changelog — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">coding-style — npm@1.1.49</p>
+<p id="footer">coding-style — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">completion — npm@1.1.49</p>
+<p id="footer">completion — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li></ul>
</div>
-<p id="footer">config — npm@1.1.49</p>
+<p id="footer">config — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
--- /dev/null
+<!doctype html>
+<html>
+ <title>dedupe</title>
+ <meta http-equiv="content-type" value="text/html;utf-8">
+ <link rel="stylesheet" type="text/css" href="../static/style.css">
+
+ <body>
+ <div id="wrapper">
+<h1><a href="../doc/dedupe.html">dedupe</a></h1> <p>Reduce duplication</p>
+
+<h2 id="SYNOPSIS">SYNOPSIS</h2>
+
+<pre><code>npm dedupe [package names...]</code></pre>
+
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
+
+<p>Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages.</p>
+
+<p>For example, consider this dependency graph:</p>
+
+<pre><code>a
++-- b <-- depends on c@1.0.x
+| `-- c@1.0.3
+`-- d <-- depends on c@~1.0.9
+ `-- c@1.0.10</code></pre>
+
+<p>In this case, <code><a href="../doc/dedupe.html">dedupe(1)</a></code> will transform the tree to:</p>
+
+<pre><code>a
++-- b
++-- d
+`-- c@1.0.10</code></pre>
+
+<p>Because of the hierarchical nature of node's module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree.</p>
+
+<p>If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted.</p>
+
+<p>If no suitable version can be found, then a warning is printed, and
+nothing is done.</p>
+
+<p>If any arguments are supplied, then they are filters, and only the
+named packages will be touched.</p>
+
+<p>Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry.</p>
+
+<p>This feature is experimental, and may change in future versions.</p>
+
+<h2 id="SEE-ALSO">SEE ALSO</h2>
+
+<ul><li><a href="../doc/ls.html">ls(1)</a></li><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
+</div>
+<p id="footer">dedupe — npm@1.1.55</p>
+<script>
+;(function () {
+var wrapper = document.getElementById("wrapper")
+var els = Array.prototype.slice.call(wrapper.getElementsByTagName("*"), 0)
+ .filter(function (el) {
+ return el.parentNode === wrapper
+ && el.tagName.match(/H[1-6]/)
+ && el.id
+ })
+var l = 2
+ , toc = document.createElement("ul")
+toc.innerHTML = els.map(function (el) {
+ var i = el.tagName.charAt(1)
+ , out = ""
+ while (i > l) {
+ out += "<ul>"
+ l ++
+ }
+ while (i < l) {
+ out += "</ul>"
+ l --
+ }
+ out += "<li><a href='#" + el.id + "'>" +
+ ( el.innerText || el.text || el.innerHTML)
+ + "</a>"
+ return out
+}).join("\n")
+toc.id = "toc"
+document.body.appendChild(toc)
+})()
+</script>
+</body></html>
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">deprecate — npm@1.1.49</p>
+<p id="footer">deprecate — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li></ul>
</div>
-<p id="footer">developers — npm@1.1.49</p>
+<p id="footer">developers — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li></ul>
</div>
-<p id="footer">disputes — npm@1.1.49</p>
+<p id="footer">disputes — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">docs — npm@1.1.49</p>
+<p id="footer">docs — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/explore.html">explore(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">edit — npm@1.1.49</p>
+<p id="footer">edit — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/submodule.html">submodule(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/edit.html">edit(1)</a></li><li><a href="../doc/rebuild.html">rebuild(1)</a></li><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">explore — npm@1.1.49</p>
+<p id="footer">explore — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li></ul>
</div>
-<p id="footer">faq — npm@1.1.49</p>
+<p id="footer">faq — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/pack.html">pack(1)</a></li><li><a href="../doc/cache.html">cache(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li></ul>
</div>
-<p id="footer">folders — npm@1.1.49</p>
+<p id="footer">folders — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/help.html">help(1)</a></li></ul>
</div>
-<p id="footer">help-search — npm@1.1.49</p>
+<p id="footer">help-search — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/npm.html">npm(1)</a></li><li><a href="../doc/README.html">README</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/help-search.html">help-search(1)</a></li><li><a href="../doc/index.html">index(1)</a></li></ul>
</div>
-<p id="footer">help — npm@1.1.49</p>
+<p id="footer">help — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<p> Manage the npm configuration file</p>
+<h2 id="npm-dedupe-1"><a href="../doc/dedupe.html">dedupe(1)</a></h2>
+
+<p> Reduce duplication</p>
+
<h2 id="npm-deprecate-1"><a href="../doc/deprecate.html">deprecate(1)</a></h2>
<p> Deprecate a version of a package</p>
<p> Display npm username</p>
</div>
-<p id="footer">index — npm@1.1.49</p>
+<p id="footer">index — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="https://github.com/isaacs/init-package-json">https://github.com/isaacs/init-package-json</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/version.html">version(1)</a></li></ul>
</div>
-<p id="footer">init — npm@1.1.49</p>
+<p id="footer">init — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/rebuild.html">rebuild(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/tag.html">tag(1)</a></li><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/shrinkwrap.html">shrinkwrap(1)</a></li></ul>
</div>
-<p id="footer">install — npm@1.1.49</p>
+<p id="footer">install — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/semver.html">semver(1)</a></li><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/version.html">version(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/rm.html">rm(1)</a></li></ul>
</div>
-<p id="footer">json — npm@1.1.49</p>
+<p id="footer">json — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">link — npm@1.1.49</p>
+<p id="footer">link — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
nested packages will <em>also</em> show the paths to the specified packages.
For example, running <code>npm ls promzard</code> in npm's source tree will show:</p>
-<pre><code>npm@1.1.49 /path/to/npm
+<pre><code>npm@1.1.55 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5</code></pre>
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/link.html">link(1)</a></li><li><a href="../doc/prune.html">prune(1)</a></li><li><a href="../doc/outdated.html">outdated(1)</a></li><li><a href="../doc/update.html">update(1)</a></li></ul>
</div>
-<p id="footer">list — npm@1.1.49</p>
+<p id="footer">list — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<h2 id="VERSION">VERSION</h2>
-<p>1.1.49</p>
+<p>1.1.55</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<ul><li><a href="../doc/help.html">help(1)</a></li><li><a href="../doc/faq.html">faq(1)</a></li><li><a href="../doc/README.html">README</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/index.html">index(1)</a></li><li><a href="../api/npm.html">npm(3)</a></li></ul>
</div>
-<p id="footer">npm — npm@1.1.49</p>
+<p id="footer">npm — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/update.html">update(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li></ul>
</div>
-<p id="footer">outdated — npm@1.1.49</p>
+<p id="footer">outdated — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/disputes.html">disputes(1)</a></li></ul>
</div>
-<p id="footer">owner — npm@1.1.49</p>
+<p id="footer">owner — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/cache.html">cache(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">pack — npm@1.1.49</p>
+<p id="footer">pack — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/root.html">root(1)</a></li><li><a href="../doc/bin.html">bin(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">prefix — npm@1.1.49</p>
+<p id="footer">prefix — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">prune — npm@1.1.49</p>
+<p id="footer">prune — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li><li><a href="../doc/deprecate.html">deprecate(1)</a></li><li><a href="../doc/tag.html">tag(1)</a></li></ul>
</div>
-<p id="footer">publish — npm@1.1.49</p>
+<p id="footer">publish — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/build.html">build(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">rebuild — npm@1.1.49</p>
+<p id="footer">rebuild — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/disputes.html">disputes(1)</a></li></ul>
</div>
-<p id="footer">registry — npm@1.1.49</p>
+<p id="footer">registry — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/README.html">README</a></li><li><a href="../doc/rm.html">rm(1)</a></li><li><a href="../doc/prune.html">prune(1)</a></li></ul>
</div>
-<p id="footer">removing-npm — npm@1.1.49</p>
+<p id="footer">removing-npm — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">restart — npm@1.1.49</p>
+<p id="footer">restart — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/prefix.html">prefix(1)</a></li><li><a href="../doc/bin.html">bin(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">root — npm@1.1.49</p>
+<p id="footer">root — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">run-script — npm@1.1.49</p>
+<p id="footer">run-script — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/developers.html">developers(1)</a></li><li><a href="../doc/install.html">install(1)</a></li></ul>
</div>
-<p id="footer">scripts — npm@1.1.49</p>
+<p id="footer">scripts — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/view.html">view(1)</a></li></ul>
</div>
-<p id="footer">search — npm@1.1.49</p>
+<p id="footer">search — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/json.html">json(1)</a></li></ul>
</div>
-<p id="footer">semver — npm@1.1.49</p>
+<p id="footer">semver — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">shrinkwrap — npm@1.1.49</p>
+<p id="footer">shrinkwrap — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/view.html">view(1)</a></li><li><a href="../doc/whoami.html">whoami(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li></ul>
</div>
-<p id="footer">star — npm@1.1.49</p>
+<p id="footer">star — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">start — npm@1.1.49</p>
+<p id="footer">start — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/test.html">test(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li></ul>
</div>
-<p id="footer">stop — npm@1.1.49</p>
+<p id="footer">stop — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/json.html">json(1)</a></li><li>git help submodule</li></ul>
</div>
-<p id="footer">submodule — npm@1.1.49</p>
+<p id="footer">submodule — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">tag — npm@1.1.49</p>
+<p id="footer">tag — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/run-script.html">run-script(1)</a></li><li><a href="../doc/scripts.html">scripts(1)</a></li><li><a href="../doc/start.html">start(1)</a></li><li><a href="../doc/restart.html">restart(1)</a></li><li><a href="../doc/stop.html">stop(1)</a></li></ul>
</div>
-<p id="footer">test — npm@1.1.49</p>
+<p id="footer">test — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/prune.html">prune(1)</a></li><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/config.html">config(1)</a></li></ul>
</div>
-<p id="footer">uninstall — npm@1.1.49</p>
+<p id="footer">uninstall — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/deprecate.html">deprecate(1)</a></li><li><a href="../doc/publish.html">publish(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li><li><a href="../doc/owner.html">owner(1)</a></li></ul>
</div>
-<p id="footer">unpublish — npm@1.1.49</p>
+<p id="footer">unpublish — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/install.html">install(1)</a></li><li><a href="../doc/outdated.html">outdated(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/folders.html">folders(1)</a></li><li><a href="../doc/list.html">list(1)</a></li></ul>
</div>
-<p id="footer">update — npm@1.1.49</p>
+<p id="footer">update — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/init.html">init(1)</a></li><li><a href="../doc/json.html">json(1)</a></li><li><a href="../doc/semver.html">semver(1)</a></li></ul>
</div>
-<p id="footer">version — npm@1.1.49</p>
+<p id="footer">version — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/search.html">search(1)</a></li><li><a href="../doc/registry.html">registry(1)</a></li><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/docs.html">docs(1)</a></li></ul>
</div>
-<p id="footer">view — npm@1.1.49</p>
+<p id="footer">view — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
<ul><li><a href="../doc/config.html">config(1)</a></li><li><a href="../doc/adduser.html">adduser(1)</a></li></ul>
</div>
-<p id="footer">whoami — npm@1.1.49</p>
+<p id="footer">whoami — npm@1.1.55</p>
<script>
;(function () {
var wrapper = document.getElementById("wrapper")
--- /dev/null
+// traverse the node_modules/package.json tree
+// looking for duplicates. If any duplicates are found,
+// then move them up to the highest level necessary
+// in order to make them no longer duplicated.
+//
+// This is kind of ugly, and really highlights the need for
+// much better "put pkg X at folder Y" abstraction. Oh well,
+// whatever. Perfect enemy of the good, and all that.
+
+var fs = require("fs")
+var asyncMap = require("slide").asyncMap
+var path = require("path")
+var readJson = require("read-package-json")
+var archy = require("archy")
+var util = require("util")
+var RegClient = require("npm-registry-client")
+var npmconf = require("npmconf")
+var npm = require("npm")
+var semver = require("semver")
+var npm = require("npm")
+var rimraf = require("rimraf")
+var log = require("npmlog")
+var npm = require("./npm.js")
+
+module.exports = dedupe
+
+dedupe.usage = "npm dedupe [pkg pkg...]"
+
+function dedupe (args, silent, cb) {
+ if (typeof silent === "function") cb = silent, silent = false
+ var dryrun = false
+ if (npm.command.match(/^find/)) dryrun = true
+ return dedupe_(npm.prefix, args, {}, dryrun, silent, cb)
+}
+
+function dedupe_ (dir, filter, unavoidable, dryrun, silent, cb) {
+ readInstalled(path.resolve(dir), {}, null, function (er, data, counter) {
+ // find out which things are dupes
+ var dupes = Object.keys(counter).filter(function (k) {
+ if (filter.length && -1 === filter.indexOf(k)) return false
+ return counter[k] > 1 && !unavoidable[k]
+ }).reduce(function (s, k) {
+ s[k] = []
+ return s
+ }, {})
+
+ // any that are unavoidable need to remain as they are. don't even
+ // try to touch them or figure it out. Maybe some day, we can do
+ // something a bit more clever here, but for now, just skip over it,
+ // and all its children.
+ ;(function U (obj) {
+ if (unavoidable[obj.name]) {
+ obj.unavoidable = true
+ }
+ if (obj.parent && obj.parent.unavoidable) {
+ obj.unavoidable = true
+ }
+ Object.keys(obj.children).forEach(function (k) {
+ U(obj.children[k])
+ })
+ })
+
+ // then collect them up and figure out who needs them
+ ;(function C (obj) {
+ if (dupes[obj.name] && !obj.unavoidable) {
+ dupes[obj.name].push(obj)
+ obj.duplicate = true
+ }
+ obj.dependents = whoDepends(obj)
+ Object.keys(obj.children).forEach(function (k) {
+ C(obj.children[k])
+ })
+ })(data)
+
+ if (dryrun) {
+ var k = Object.keys(dupes)
+ if (!k.length) return cb()
+ return npm.commands.ls(k, silent, cb)
+ }
+
+ var summary = Object.keys(dupes).map(function (n) {
+ return [n, dupes[n].filter(function (d) {
+ return d && d.parent && !d.parent.duplicate && !d.unavoidable
+ }).map(function M (d) {
+ return [d.path, d.version, d.dependents.map(function (k) {
+ return [k.path, k.version, k.dependencies[d.name] || ""]
+ })]
+ })]
+ }).map(function (item) {
+ var name = item[0]
+ var set = item[1]
+
+ var ranges = set.map(function (i) {
+ return i[2].map(function (d) {
+ return d[2]
+ })
+ }).reduce(function (l, r) {
+ return l.concat(r)
+ }, []).map(function (v, i, set) {
+ if (set.indexOf(v) !== i) return false
+ return v
+ }).filter(function (v) {
+ return v !== false
+ })
+
+ var locs = set.map(function (i) {
+ return i[0]
+ })
+
+ var versions = set.map(function (i) {
+ return i[1]
+ }).filter(function (v, i, set) {
+ return set.indexOf(v) === i
+ })
+
+ var has = set.map(function (i) {
+ return [i[0], i[1]]
+ }).reduce(function (set, kv) {
+ set[kv[0]] = kv[1]
+ return set
+ }, {})
+
+ var loc = locs.length ? locs.reduce(function (a, b) {
+ // a=/path/to/node_modules/foo/node_modules/bar
+ // b=/path/to/node_modules/elk/node_modules/bar
+ // ==/path/to/node_modules/bar
+ a = a.split(/\/node_modules\//)
+ b = b.split(/\/node_modules\//)
+ var name = a.pop()
+ b.pop()
+ // find the longest chain that both A and B share.
+ // then push the name back on it, and join by /node_modules/
+ var res = []
+ for (var i = 0, al = a.length, bl = b.length; i < al && i < bl && a[i] === b[i]; i++);
+ return a.slice(0, i).concat(name).join("/node_modules/")
+ }) : undefined
+
+ return [item[0], { item: item
+ , ranges: ranges
+ , locs: locs
+ , loc: loc
+ , has: has
+ , versions: versions
+ }]
+ }).filter(function (i) {
+ return i[1].loc
+ })
+
+ findVersions(npm, summary, function (er, set) {
+ if (er) return cb(er)
+ if (!set.length) return cb()
+ installAndRetest(set, filter, dir, unavoidable, silent, cb)
+ })
+ })
+}
+
+function installAndRetest (set, filter, dir, unavoidable, silent, cb) {
+ //return cb(null, set)
+ var remove = []
+
+ asyncMap(set, function (item, cb) {
+ // [name, has, loc, locMatch, regMatch, others]
+ var name = item[0]
+ var has = item[1]
+ var where = item[2]
+ var locMatch = item[3]
+ var regMatch = item[4]
+ var others = item[5]
+
+ // nothing to be done here. oh well. just a conflict.
+ if (!locMatch && !regMatch) {
+ log.warn("unavoidable conflict", item[0], item[1])
+ log.warn("unavoidable conflict", "Not de-duplicating")
+ unavoidable[item[0]] = true
+ return cb()
+ }
+
+ // nothing to do except to clean up the extraneous deps
+ if (locMatch && has[where] === locMatch) {
+ remove.push.apply(remove, others)
+ return cb()
+ }
+
+ if (regMatch) {
+ var what = name + "@" + regMatch
+ // where is /path/to/node_modules/foo/node_modules/bar
+ // for package "bar", but we need it to be just
+ // /path/to/node_modules/foo
+ where = where.split(/\/node_modules\//)
+ where.pop()
+ where = where.join("/node_modules/")
+ remove.push.apply(remove, others)
+
+ return npm.commands.install(where, what, cb)
+ }
+
+ // hrm?
+ return cb(new Error("danger zone\n" + name + " " +
+ + regMatch + " " + locMatch))
+
+ }, function (er, installed) {
+ if (er) return cb(er)
+ asyncMap(remove, rimraf, function (er) {
+ if (er) return cb(er)
+ remove.forEach(function (r) {
+ log.info("rm", r)
+ })
+ dedupe_(dir, filter, unavoidable, false, silent, cb)
+ })
+ })
+}
+
+function findVersions (npm, summary, cb) {
+ // now, for each item in the summary, try to find the maximum version
+ // that will satisfy all the ranges. next step is to install it at
+ // the specified location.
+ asyncMap(summary, function (item, cb) {
+ var name = item[0]
+ var data = item[1]
+ var loc = data.loc
+ var locs = data.locs.filter(function (l) {
+ return l !== loc
+ })
+
+ // not actually a dupe, or perhaps all the other copies were
+ // children of a dupe, so this'll maybe be picked up later.
+ if (locs.length === 0) {
+ return cb()
+ }
+
+ // { <folder>: <version> }
+ var has = data.has
+
+ // the versions that we already have.
+ // if one of these is ok, then prefer to use that.
+ // otherwise, try fetching from the registry.
+ var versions = data.versions
+
+ var ranges = data.ranges
+ npm.registry.get(name, function (er, data) {
+ var regVersions = er ? [] : Object.keys(data.versions)
+ var locMatch = bestMatch(versions, ranges)
+ var regMatch = bestMatch(regVersions, ranges)
+
+ cb(null, [[name, has, loc, locMatch, regMatch, locs]])
+ })
+ }, cb)
+}
+
+function bestMatch (versions, ranges) {
+ return versions.filter(function (v) {
+ return !ranges.some(function (r) {
+ return !semver.satisfies(v, r)
+ })
+ }).sort(semver.compare).pop()
+}
+
+
+function readInstalled (dir, counter, parent, cb) {
+ var pkg, children, realpath
+
+ fs.realpath(dir, function (er, rp) {
+ realpath = rp
+ next()
+ })
+
+ readJson(path.resolve(dir, "package.json"), function (er, data) {
+ if (er) return cb() // not a package, probably.
+ counter[data.name] = counter[data.name] || 0
+ counter[data.name]++
+ pkg =
+ { _id: data._id
+ , name: data.name
+ , version: data.version
+ , dependencies: data.dependencies || {}
+ , optionalDependencies: data.optionalDependencies || {}
+ , devDependencies: data.devDependencies || {}
+ , bundledDependencies: data.bundledDependencies || []
+ , path: dir
+ , realPath: dir
+ , children: {}
+ , parent: parent
+ , family: Object.create(parent ? parent.family : null)
+ , unavoidable: false
+ , duplicate: false
+ }
+ if (parent) {
+ parent.children[data.name] = pkg
+ parent.family[data.name] = pkg
+ }
+ next()
+ })
+
+ fs.readdir(path.resolve(dir, "node_modules"), function (er, c) {
+ children = c || [] // error is ok, just means no children.
+ next()
+ })
+
+ function next () {
+ if (!children || !pkg || !realpath) return
+
+ // ignore devDependencies. Just leave them where they are.
+ children = children.filter(function (c) {
+ return !pkg.devDependencies.hasOwnProperty(c)
+ })
+
+ pkg.realPath = realpath
+ if (pkg.realPath !== pkg.path) children = []
+ var d = path.resolve(dir, "node_modules")
+ asyncMap(children, function (child, cb) {
+ readInstalled(path.resolve(d, child), counter, pkg, cb)
+ }, function (er) {
+ cb(er, pkg, counter)
+ })
+ }
+}
+
+function whoDepends (pkg) {
+ var start = pkg.parent || pkg
+ return whoDepends_(pkg, [], start)
+}
+
+function whoDepends_ (pkg, who, test) {
+ if (test !== pkg &&
+ test.dependencies[pkg.name] &&
+ test.family[pkg.name] === pkg) {
+ who.push(test)
+ }
+ Object.keys(test.children).forEach(function (n) {
+ whoDepends_(pkg, who, test.children[n])
+ })
+ return who
+}
+
, "login": "adduser"
, "add-user": "adduser"
, "tst": "test"
+ , "find-dupes": "dedupe"
+ , "ddp": "dedupe"
}
, aliasNames = Object.keys(aliases)
, "prune"
, "submodule"
, "pack"
+ , "dedupe"
, "rebuild"
, "link"
} catch (e) { token = null }
}
- npm.registry = new RegClient(
- { registry: npm.config.get("registry")
- , cache: npm.config.get("cache")
- , auth: npm.config.get("_auth")
- , token: token
- , alwaysAuth: npm.config.get("always-auth")
- , email: npm.config.get("email")
- , proxy: npm.config.get("proxy")
- , tag: npm.config.get("tag")
- , ca: npm.config.get("ca")
- , strictSSL: npm.config.get("strict-ssl")
- , userAgent: npm.config.get("user-agent")
- , E404: npm.E404
- , EPUBLISHCONFLICT: npm.EPUBLISHCONFLICT
- , log: log
- , retries: npm.config.get("fetch-retries")
- , retryFactor: npm.config.get("fetch-retry-factor")
- , retryMinTimeout: npm.config.get("fetch-retry-mintimeout")
- , retryMaxTimeout: npm.config.get("fetch-retry-maxtimeout")
- , cacheMin: npm.config.get("cache-min")
- , cacheMax: npm.config.get("cache-max")
- })
+ npm.registry = new RegClient(npm.config)
// save the token cookie in the config file
if (npm.registry.couchLogin) {
}
})
- findPrefix(gp, function (er, gp) {
- Object.defineProperty(npm, "globalPrefix",
- { get : function () { return gp }
- , set : function (r) { return gp = r }
- , enumerable : true
- })
- // the prefix MUST exist, or else nothing works.
- mkdir(gp, next)
- })
+ gp = path.resolve(gp)
+ Object.defineProperty(npm, "globalPrefix",
+ { get : function () { return gp }
+ , set : function (r) { return gp = r }
+ , enumerable : true
+ })
+ // the prefix MUST exist, or else nothing works.
+ mkdir(gp, next)
+
var i = 2
, errState = null
module.exports = publish
var npm = require("./npm.js")
- , registry = npm.registry
, log = require("npmlog")
, tar = require("./utils/tar.js")
, path = require("path")
, fs = require("graceful-fs")
, lifecycle = require("./utils/lifecycle.js")
, chain = require("slide").chain
+ , Conf = require("npmconf").Conf
+ , RegClient = require("npm-registry-client")
publish.usage = "npm publish <tarball>"
+ "\nnpm publish <folder>"
if (!data) return cb(new Error("no package.json file found"))
// check for publishConfig hash
+ var registry = npm.registry
if (data.publishConfig) {
- Object.keys(data.publishConfig).forEach(function (k) {
- log.info("publishConfig", k + "=" + data.publishConfig[k])
- npm.config.set(k, data.publishConfig[k])
- })
+ var pubConf = new Conf(npm.config)
+ pubConf.unshift(data.publishConfig)
+ registry = new RegClient(pubConf)
}
data._npmVersion = npm.version
("This package has been marked as private\n"
+"Remove the 'private' field from the package.json to publish it."))
- regPublish(data, isRetry, arg, cachedir, cb)
-}
-
-function regPublish (data, isRetry, arg, cachedir, cb) {
var tarball = cachedir + ".tgz"
registry.publish(data, tarball, function (er) {
if (er && er.code === "EPUBLISHCONFLICT"
,"Move it away, and try again."].join("\n"))
break
+ case "ENEEDAUTH":
+ log.error("need auth", [er.message
+ ,"You need to authorize this machine using `npm adduser`"
+ ].join("\n"))
+ break
+
case "ENOTSUP":
if (er.required) {
log.error("notsup", [er.message
"Auth required and none provided. Please run 'npm adduser'"))
}
- var proxy = npm.config.get( remote.protocol === "https:"
- ? "https-proxy"
- : "proxy")
+ var proxy
+ if (remote.protocol !== "https:" || !(proxy = npm.config.get("https-proxy"))) {
+ proxy = npm.config.get("proxy")
+ }
var opts = { url: remote
, proxy: proxy
}
p = path.resolve(p)
- if (npm.config.get("global")) return cb(null, p)
// if there's no node_modules folder, then
// walk up until we hopefully find one.
// if none anywhere, then use cwd.
fields.forEach(function (f) {
var d = cleanup(data[v][f])
if (showVersions || showFields || typeof d !== "string") {
- d = util.inspect(cleanup(data[v][f]), false, 5, true)
+ d = util.inspect(cleanup(data[v][f]), false, 5, npm.color)
}
if (f && showFields) f += " = "
if (d.indexOf("\n") !== -1) d = "\n" + d
--- /dev/null
+.\" Generated with Ronnjs 0.3.8
+.\" http://github.com/kapouer/ronnjs/
+.
+.TH "NPM\-DEDUPE" "1" "August 2012" "" ""
+.
+.SH "NAME"
+\fBnpm-dedupe\fR \-\- Reduce duplication
+.
+.SH "SYNOPSIS"
+.
+.nf
+npm dedupe [package names\.\.\.]
+.
+.fi
+.
+.SH "DESCRIPTION"
+Searches the local package tree and attempts to simplify the overall
+structure by moving dependencies further up the tree, where they can
+be more effectively shared by multiple dependent packages\.
+.
+.P
+For example, consider this dependency graph:
+.
+.IP "" 4
+.
+.nf
+a
++\-\- b <\-\- depends on c@1\.0\.x
+| `\-\- c@1\.0\.3
+`\-\- d <\-\- depends on c@~1\.0\.9
+ `\-\- c@1\.0\.10
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In this case, \fBnpm help dedupe\fR will transform the tree to:
+.
+.IP "" 4
+.
+.nf
+a
++\-\- b
++\-\- d
+`\-\- c@1\.0\.10
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Because of the hierarchical nature of node\'s module lookup, b and d
+will both get their dependency met by the single c package at the root
+level of the tree\.
+.
+.P
+If a suitable version exists at the target location in the tree
+already, then it will be left untouched, but the other duplicates will
+be deleted\.
+.
+.P
+If no suitable version can be found, then a warning is printed, and
+nothing is done\.
+.
+.P
+If any arguments are supplied, then they are filters, and only the
+named packages will be touched\.
+.
+.P
+Note that this operation transforms the dependency tree, and may
+result in packages getting updated versions, perhaps from the npm
+registry\.
+.
+.P
+This feature is experimental, and may change in future versions\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+npm help ls
+.
+.IP "\(bu" 4
+npm help update
+.
+.IP "\(bu" 4
+npm help install
+.
+.IP "" 0
+
.SH "npm help config"
Manage the npm configuration file
.
+.SH "npm help dedupe"
+ Reduce duplication
+.
.SH "npm help deprecate"
Deprecate a version of a package
.
.IP "" 4
.
.nf
-npm@1.1.49 /path/to/npm
+npm@1.1.55 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.
.fi
.
.SH "VERSION"
-1.1.49
+1.1.55
.
.SH "DESCRIPTION"
npm is the package manager for the Node JavaScript platform\. It puts
.fi
.
.SH "VERSION"
-1.1.49
+1.1.55
.
.SH "DESCRIPTION"
This is the API documentation for npm\.
, req = { uri: u, headers: h, json: true }
request.del(req, function (er, res, data) {
- if (er || res.statusCode !== 200) {
+ if (er || (res.statusCode !== 200 && res.statusCode !== 404)) {
return cb(er, res, data)
}
},
"name": "couch-login",
"description": "A module for doing logged-in requests to a couchdb server",
- "version": "0.1.9",
+ "version": "0.1.10",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/couch-login.git"
"tap": "~0.2.4"
},
"readme": "# couch-login\n\nThis module lets you log into couchdb to get a session token, then make\nrequests using that session. It is basically just a thin wrapper around\n[@mikeal's request module](https://github.com/mikeal/request).\n\nThis is handy if you want a user to take actions in a couchdb database\non behalf of a user, without having to store their couchdb username and\npassword anywhere. (You do need to store the AuthSession token\nsomewhere, though.)\n\n## Usage\n\n```javascript\nvar CouchLogin = require('couch-login')\n\n// Nothing about this module is http-server specific of course.\n// You could also use it to do authenticated requests against\n// a couchdb using sessions and storing the token somewhere else.\n\nhttp.createServer(function (req, res) {\n var couch = new CouchLogin('http://my-couch.iriscouch.com:5984/')\n\n // .. look up the token in the user's session or whatever ..\n // Look at couch.decorate(req, res) for more on doing that\n // automatically, below.\n\n if (sessionToken) {\n // this user already logged in.\n couch.token = sessionToken\n\n // now we can do things on their behalf, like:\n // 1. View their session info.\n // like doing request.get({ uri: couch + '/_session', ... })\n // but with the cookie and whatnot\n\n couch.get('/_session', function (er, resp, data) {\n // er = some kind of communication error.\n // resp = response object from the couchdb request.\n // data = parsed JSON response body.\n if (er || resp.statusCode !== 200) {\n res.statusCode = resp.statusCode || 403\n return res.end('Invalid login or something')\n }\n\n // now we have the session info, we know who this user is.\n // hitting couchdb for this on every request is kinda costly,\n // so maybe you should store the username wherever you're storing\n // the sessionToken. RedSess is a good util for this, if you're\n // into redis. And if you're not into redis, you're crazy,\n // because it is awesome.\n\n // now let's get the user record.\n // note that this will 404 for anyone other than the user,\n // unless they're a server admin.\n couch.get('/_users/org.couchdb.user:' + data.userCtx.name, etc)\n\n // PUTs and DELETEs will also use their session, of course, so\n // your validate_doc_update's will see their info in userCtx\n })\n\n } else {\n // don't have a sessionToken.\n // get a username and password from the post body or something.\n // maybe redirect to a /login page or something to ask for that.\n var login = { name: name, password: password }\n couch.login(login, function (er, resp, data) {\n // again, er is an error, resp is the response obj, data is the json\n if (er || resp.statusCode !== 200) {\n res.statusCode = resp.statusCode || 403\n return res.end('Invalid login or something')\n }\n\n // the data is something like\n // {\"ok\":true,\"name\":\"testuser\",\"roles\":[]}\n // and couch.token is the token you'll need to save somewhere.\n\n // at this point, you can start making authenticated requests to\n // couchdb, or save data in their session, or do whatever it is\n // that you need to do.\n\n res.statusCode = 200\n res.write(\"Who's got two thumbs and just logged you into couch?\\n\")\n setTimeout(function () {\n res.end(\"THIS GUY!\")\n }, 500)\n })\n }\n})\n```\n\n## Class: CouchLogin\n### new CouchLogin(couchdbUrl, token)\n\nCreate a new CouchLogin object bound to the couchdb url.\n\nIn addition to these, the `get`, `post`, `put`, and `del` methods all\nproxy to the associated method on [request](https://github.com/mikeal/request).\n\nHowever, as you'll note in the example above, only the pathname portion\nof the url is required. Urls will be appended to the couchdb url passed\ninto the constructor.\n\nIf you have to talk to more than one couchdb, then you'll need more than\none CouchLogin object, for somewhat obvious reasons.\n\nAll callbacks get called with the following arguments, which are exactly\nidentical to the arguments passed to a `request` callback.\n\n* `er` {Error | null} Set if a communication error happens.\n* `resp` {HTTP Response} The response from the request to couchdb\n* `data` {Object} The parsed JSON data from couch\n\nIf the token is the string \"anonymous\", then it will not attempt to log\nin before making requests. If the token is not \"anonymous\", then it\nmust be an object with the appropriate fields.\n\n### couch.token\n\n* {Object}\n\nAn object representing the couchdb session token. (Basically just a\ncookie and a timeout.)\n\nIf the token has already timed out, then setting it will have no effect.\n\n### couch.tokenSet\n\nIf set, this method is called whenever the token is saved.\n\nFor example, you could assign a function to this method to save the\ntoken into a redis session, a cookie, or in some other database.\n\nTakes a callback which should be called when the token is saved.\n\n### couch.tokenGet\n\nIf set, this method is called to look up the token on demand.\n\nThe inverse of couch.tokenSet. Takes a callback which is called with\nthe `cb(er || null, token)`.\n\n### couch.tokenDel\n\nIf set, this method is called to delete the token when it should be\ndiscarded.\n\nRelated to tokenGet and tokenSet. Takes a callback which should be\ncalled when the token is deleted.\n\n### couch.anonymous()\n\nReturn a new CouchLogin object that points at the same couchdb server,\nbut doesn't try to log in before making requests.\n\nThis is handy for situations where the user is not logged in at the\nmoment, but a request needs to be made anyway, and does not require\nauthorization.\n\n### couch.login(auth, callback)\n\n* `auth` {Object} The login details\n * `name` {String}\n * `password` {String}\n* `callback` {Function}\n\nWhen the callback is called, the `couch.token` will already have been\nset (assuming it worked!), so subsequent requests will be done as that\nuser.\n\n### couch.get(path, callback)\n\nGET the supplied path from the couchdb using the credentials on the\ntoken.\n\nFails if the token is invalid or expired.\n\n### couch.del(path, callback)\n\nDELETE the supplied path from the couchdb using the credentials on the\ntoken.\n\nFails if the token is invalid or expired.\n\n### couch.post(path, data, callback)\n\nPOST the data to the supplied path in the couchdb, using the credentials\non the token.\n\nFails if the token is invalid or expired.\n\n### couch.put(path, data, callback)\n\nPUT the data to the supplied path in the couchdb, using the credentials\non the token.\n\nFails if the token is invalid or expired.\n\n### couch.changePass(newAuth, callback)\n\nMust already be logged in. Updates the `_users` document with new salt\nand hash, and re-logs in with the new credentials. Callback is called\nwith the same arguments as login, or the first step of the process that\nfailed.\n\n### couch.signup(userData, callback)\n\nCreate a new user account. The userData must contain at least a `name`\nand `password` field. Any additional data will be copied to the user\nrecord. The `_id`, `name`, `roles`, `type`, `password_sha`, `salt`, and\n`date` fields are generated.\n\nAlso signs in as the newly created user, on successful account creation.\n\n### couch.deleteAccount(name, callback)\n\nDeletes a user account. If not logged in as the user, or a server\nadmin, then the request will fail.\n\nNote that this immediately invalidates any session tokens for the\ndeleted user account. If you are deleting the user's record, then you\nought to follow this with `couch.logout(callback)` so that it won't try\nto re-use the invalid session.\n\n### couch.logout(callback)\n\nDelete the session out of couchdb. This makes the token permanently\ninvalid, and deletes it.\n\n### couch.decorate(req, res)\n\nSet up `req.couch` and `res.couch` as references to this couch login\ninstance.\n\nAdditionall, if `req.session` or `res.session` is set, then it'll call\n`session.get('couch_token', cb)` as the tokenGet method,\n`session.set('couch_token', token, cb)` as the tokenSet method, and\n`session.del('couch_token', cb)` as the tokenDel method.\n\nThis works really nice with\n[RedSess](https://github.com/isaacs/redsess).\n",
- "_id": "couch-login@0.1.9",
- "_from": "couch-login@latest"
+ "_id": "couch-login@0.1.10",
+ "_from": "couch-login@~0.1.9"
}
+++ /dev/null
-node_modules/
-npm-debug.log
\ No newline at end of file
+++ /dev/null
---- /dev/null
-+++ .gitignore
-@@ -0,0 +1,2 @@
-+node_modules/
-+npm-debug.log
\ No newline at end of file
+++ /dev/null
-var mkdirp = require('mkdirp');
-
-mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
- if (err) console.error(err)
- else console.log('pow!')
-});
+++ /dev/null
---- examples/pow.js
-+++ examples/pow.js
-@@ -1,6 +1,15 @@
--var mkdirp = require('mkdirp').mkdirp;
-+var mkdirp = require('../').mkdirp,
-+ mkdirpSync = require('../').mkdirpSync;
-
- mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
- if (err) console.error(err)
- else console.log('pow!')
- });
-+
-+try {
-+ mkdirpSync('/tmp/bar/foo/baz', 0755);
-+ console.log('double pow!');
-+}
-+catch (ex) {
-+ console.log(ex);
-+}
\ No newline at end of file
});
break;
- case 'EISDIR':
- case 'EPERM':
- // Operation not permitted or already is a dir.
- // This is the error you get when trying to mkdir('c:/')
- // on windows, or mkdir('/') on unix. Make sure it's a
- // dir by falling through to the EEXIST case.
- case 'EROFS':
- // a read-only file system.
- // However, the dir could already exist, in which case
- // the EROFS error will be obscuring a EEXIST!
- // Fallthrough to that case.
- case 'EEXIST':
+ // In the case of any other error, just see if there's a dir
+ // there already. If so, then hooray! If not, then something
+ // is borked.
+ default:
fs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
else cb(null, made);
});
break;
-
- default:
- cb(er, made);
- break;
}
});
}
sync(p, mode, made);
break;
- case 'EEXIST' :
+ // In the case of any other error, just see if there's a dir
+ // there already. If so, then hooray! If not, then something
+ // is borked.
+ default:
var stat;
try {
stat = fs.statSync(p);
}
if (!stat.isDirectory()) throw err0;
break;
- default :
- throw err0
- break;
}
}
{
"name": "mkdirp",
"description": "Recursively mkdir, like `mkdir -p`",
- "version": "0.3.3",
+ "version": "0.3.4",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
],
"repository": {
"type": "git",
- "url": "git://github.com/substack/node-mkdirp.git"
+ "url": "http://github.com/substack/node-mkdirp.git"
},
"scripts": {
"test": "tap test/*.js"
"engines": {
"node": "*"
},
- "_npmUser": {
- "name": "isaacs",
- "email": "i@izs.me"
- },
- "_id": "mkdirp@0.3.3",
- "dependencies": {},
- "optionalDependencies": {},
- "_engineSupported": true,
- "_npmVersion": "1.1.24",
- "_nodeVersion": "v0.7.10-pre",
- "_defaultsLoaded": true,
- "_from": "mkdirp@0.3"
+ "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n var mkdirp = require('mkdirp');\n \n mkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n });\n\nOutput\n pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n",
+ "_id": "mkdirp@0.3.4",
+ "_from": "mkdirp@~0.3.3"
}
}],
[ 'OS=="win"', {
'libraries': [ '-l<(node_root_dir)/$(Configuration)/node.lib' ],
+ # warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent<T>'
+ # needs to have dll-interface to be used by clients of class 'node::ObjectWrap'
+ 'msvs_disabled_warnings': [ 4251 ],
}],
[ 'OS=="freebsd" or OS=="openbsd" or OS=="solaris" or (OS=="linux" and target_arch!="ia32")', {
'cflags': [ '-fPIC' ],
argv.push('/clp:Verbosity=minimal')
}
- // Turn off the Microsoft logo on Windows
if (win) {
+ // Turn off the Microsoft logo on Windows
argv.push('/nologo')
+
+ // Fix "warning MSB8012: TargetExt(.dll) does not match
+ // the Linker's OutputFile property value (.node)"
+ argv.push('/property:TargetExt=.node')
}
// Specify the build type, Release by default
, proxy: String // 'install'
, nodedir: String // 'configure'
, loglevel: String // everywhere
+ , python: String // 'configure'
}
/**
"bindings",
"gyp"
],
- "version": "0.6.5",
+ "version": "0.6.7",
"installVersion": 9,
"author": {
"name": "Nathan Rajlich",
"node": ">= 0.6.0"
},
"readme": "node-gyp\n=========\n### Node.js native addon build tool\n\n`node-gyp` is a cross-platform command-line tool written in Node.js for compiling\nnative addon modules for Node.js, which takes away the pain of dealing with the\nvarious differences in build platforms. It is the replacement to the `node-waf`\nprogram which is removed for node `v0.8`. If you have a native addon for node that\nstill has a `wscript` file, then you should definitely add a `binding.gyp` file\nto support the latest versions of node.\n\nMultiple target versions of node are supported (i.e. `0.6`, `0.7`,..., `1.0`,\netc.), regardless of what version of node is actually installed on your system\n(`node-gyp` downloads the necessary development files for the target version).\n\n#### Features:\n\n * Easy to use, consistent interface\n * Same commands to build your module on every platform\n * Supports multiple target versions of Node\n\n\nInstallation\n------------\n\nYou can install with `npm`:\n\n``` bash\n$ npm install -g node-gyp\n```\n\nYou will also need to install:\n\n * On Unix:\n * `python`\n * `make`\n * A proper C/C++ compiler toolchain, like GCC\n * On Windows:\n * [Python][windows-python] ([`v2.7.2`][windows-python-v2.7.2] recommended, `v3.x.x` not yet supported)\n * Microsoft Visual C++ ([Express][msvc] version works well)\n * For 64-bit builds of node and native modules you will _also_ need the [Windows 7 64-bit SDK][win7sdk]\n\nHow to Use\n----------\n\nTo compile your native addon, first go to its root directory:\n\n``` bash\n$ cd my_node_addon\n```\n\nThe next step is to generate the appropriate project build files for the current\nplatform. Use `configure` for that:\n\n``` bash\n$ node-gyp configure\n```\n\n__Note__: The `configure` step looks for the `binding.gyp` file in the current\ndirectory to processs. See below for instructions on creating the `binding.gyp` file.\n\nNow you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file\n(on Windows) in the `build/` directory. Next invoke the `build` command:\n\n``` bash\n$ node-gyp build\n```\n\nNow you have your compiled `.node` bindings file! The compiled bindings end up\nin `build/Debug/` or `build/Release/`, depending on the build mode. At this point\nyou can require the `.node` file with Node and run your tests!\n\n__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or\n`-d`) switch when running the either `configure` or `build` command.\n\n\nThe \"binding.gyp\" file\n----------------------\n\nPreviously when node had `node-waf` you had to write a `wscript` file. The\nreplacement for that is the `binding.gyp` file, which describes the configuration\nto build your module in a JSON-like format. This file gets placed in the root of\nyour package, alongside the `package.json` file.\n\nA barebones `gyp` file appropriate for building a node addon looks like:\n\n``` json\n{\n \"targets\": [\n {\n \"target_name\": \"binding\",\n \"sources\": [ \"src/binding.cc\" ]\n }\n ]\n}\n```\n\nSome additional resources for writing `gyp` files:\n\n * [\"Hello World\" node addon example](https://github.com/joyent/node/tree/master/test/addons/hello-world)\n * [gyp user documentation](http://code.google.com/p/gyp/wiki/GypUserDocumentation)\n * [gyp input format reference](http://code.google.com/p/gyp/wiki/InputFormatReference)\n * [*\"binding.gyp\" files out in the wild* wiki page](https://github.com/TooTallNate/node-gyp/wiki/%22binding.gyp%22-files-out-in-the-wild)\n\n\nCommands\n--------\n\n`node-gyp` responds to the following commands:\n\n| **Command** | **Description**\n|:--------------|:---------------------------------------------------------------\n| `build` | Invokes `make`/`msbuild.exe` and builds the native addon\n| `clean` | Removes any the `build` dir if it exists\n| `configure` | Generates project build files for the current platform\n| `rebuild` | Runs \"clean\", \"configure\" and \"build\" all in a row\n| `install` | Installs node development header files for the given version\n| `list` | Lists the currently installed node development file versions\n| `remove` | Removes the node development header files for the given version\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n[windows-python]: http://www.python.org/getit/windows\n[windows-python-v2.7.2]: http://www.python.org/download/releases/2.7.2#download\n[msvc]: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express\n[win7sdk]: http://www.microsoft.com/download/en/details.aspx?displayLang=en&id=8279\n",
- "_id": "node-gyp@0.6.5",
+ "_id": "node-gyp@0.6.7",
"_from": "node-gyp@~0.6.4"
}
+++ /dev/null
-node_modules
-.DS_Store
+++ /dev/null
-Copyright (c) 2010 Robert Kieffer
-
-Dual licensed under the [MIT](http://en.wikipedia.org/wiki/MIT_License) and [GPL](http://en.wikipedia.org/wiki/GNU_General_Public_License) licenses.
+++ /dev/null
-# node-uuid
-
-Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
-
-Features:
-
-* Generate RFC4122 version 1 or version 4 UUIDs
-* Runs in node.js and all browsers.
-* Cryptographically strong random # generation on supporting platforms
-* 1.1K minified and gzip'ed (Want something smaller? Check this [crazy shit](https://gist.github.com/982883) out! )
-* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)
-
-## Getting Started
-
-Install it in your browser:
-
-```html
-<script src="uuid.js"></script>
-```
-
-Or in node.js:
-
-```
-npm install node-uuid
-```
-
-```javascript
-var uuid = require('node-uuid');
-```
-
-Then create some ids ...
-
-```javascript
-// Generate a v1 (time-based) id
-uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-
-// Generate a v4 (random) id
-uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
-```
-
-## API
-
-### uuid.v1([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v1 (timestamp-based) UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
- * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomnly generated ID. See note 1.
- * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence. Default: An internally maintained clockseq is used.
- * `msecs` - (Number | Date) Time in milliseconds since unix Epoch. Default: The current time is used.
- * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Notes:
-
-1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v1({
- node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
- clockseq: 0x1234,
- msecs: new Date('2011-11-01').getTime(),
- nsecs: 5678
-}); // -> "710b962e-041c-11e1-9234-0123456789ab"
-```
-
-Example: In-place generation of two binary IDs
-
-```javascript
-// Generate two ids in an array
-var arr = new Array(32); // -> []
-uuid.v1(null, arr, 0); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-uuid.v1(null, arr, 16); // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-
-// Optionally use uuid.unparse() to get stringify the ids
-uuid.unparse(buffer); // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'
-uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'
-```
-
-### uuid.v4([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v4 UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
- * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
- * `rng` - (Function) Random # generator to use. Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v4({
- random: [
- 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
- 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
- ]
-});
-// -> "109156be-c4fb-41ea-b1b4-efe1671c5836"
-```
-
-Example: Generate two IDs in a single buffer
-
-```javascript
-var buffer = new Array(32); // (or 'new Buffer' in node.js)
-uuid.v4(null, buffer, 0);
-uuid.v4(null, buffer, 16);
-```
-
-### uuid.parse(id[, buffer[, offset]])
-### uuid.unparse(buffer[, offset])
-
-Parse and unparse UUIDs
-
- * `id` - (String) UUID(-like) string
- * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used
- * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0
-
-Example parsing and unparsing a UUID string
-
-```javascript
-var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>
-var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'
-```
-
-### uuid.noConflict()
-
-(Browsers only) Set `uuid` property back to it's previous value.
-
-Returns the node-uuid object.
-
-Example:
-
-```javascript
-var myUuid = uuid.noConflict();
-myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-```
-
-## Deprecated APIs
-
-Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.
-
-### uuid([format [, buffer [, offset]]])
-
-uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).
-
-### uuid.BufferClass
-
-The class of container created when generating binary uuid data if no buffer argument is specified. This is expected to go away, with no replacement API.
-
-## Testing
-
-In node.js
-
-```
-> cd test
-> node uuid.js
-```
-
-In Browser
-
-```
-open test/test.html
-```
-
-### Benchmarking
-
-Requires node.js
-
-```
-npm install uuid uuid-js
-node test/benchmark.js
-```
-
-For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)
-
-For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).
-
-## Release notes
-
-v1.3.2:
-* Improve tests and handling of v1() options (Issue #24)
-* Expose RNG option to allow for perf testing with different generators
-
-v1.3:
-* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
-* Support for node.js crypto API
-* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code
+++ /dev/null
-{
- "name" : "node-uuid",
- "description" : "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
- "url" : "http://github.com/broofa/node-uuid",
- "keywords" : ["uuid", "guid", "rfc4122"],
- "author" : "Robert Kieffer <robert@broofa.com>",
- "contributors" : [
- {"name": "Christoph Tavan <dev@tavan.de>", "github": "https://github.com/ctavan"}
- ],
- "dependencies" : {},
- "lib" : ".",
- "main" : "./uuid.js",
- "version" : "1.3.3"
-}
+++ /dev/null
-// node-uuid/uuid.js
-//
-// Copyright (c) 2010 Robert Kieffer
-// Dual licensed under the MIT and GPL licenses.
-// Documentation and details at https://github.com/broofa/node-uuid
-(function() {
- var _global = this;
-
- // Unique ID creation requires a high quality random # generator, but
- // Math.random() does not guarantee "cryptographic quality". So we feature
- // detect for more robust APIs, normalizing each method to return 128-bits
- // (16 bytes) of random data.
- var mathRNG, nodeRNG, whatwgRNG;
-
- // Math.random()-based RNG. All platforms, very fast, unknown quality
- var _rndBytes = new Array(16);
- mathRNG = function() {
- var r, b = _rndBytes, i = 0;
-
- for (var i = 0, r; i < 16; i++) {
- if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
- b[i] = r >>> ((i & 0x03) << 3) & 0xff;
- }
-
- return b;
- }
-
- // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
- // WebKit only (currently), moderately fast, high quality
- if (_global.crypto && crypto.getRandomValues) {
- var _rnds = new Uint32Array(4);
- whatwgRNG = function() {
- crypto.getRandomValues(_rnds);
-
- for (var c = 0 ; c < 16; c++) {
- _rndBytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff;
- }
- return _rndBytes;
- }
- }
-
- // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
- // Node.js only, moderately fast, high quality
- try {
- var _rb = require('crypto').randomBytes;
- nodeRNG = _rb && function() {
- return _rb(16);
- };
- } catch (e) {}
-
- // Select RNG with best quality
- var _rng = nodeRNG || whatwgRNG || mathRNG;
-
- // Buffer class to use
- var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
-
- // Maps for number <-> hex string conversion
- var _byteToHex = [];
- var _hexToByte = {};
- for (var i = 0; i < 256; i++) {
- _byteToHex[i] = (i + 0x100).toString(16).substr(1);
- _hexToByte[_byteToHex[i]] = i;
- }
-
- // **`parse()` - Parse a UUID into it's component bytes**
- function parse(s, buf, offset) {
- var i = (buf && offset) || 0, ii = 0;
-
- buf = buf || [];
- s.toLowerCase().replace(/[0-9a-f]{2}/g, function(byte) {
- if (ii < 16) { // Don't overflow!
- buf[i + ii++] = _hexToByte[byte];
- }
- });
-
- // Zero out remaining bytes if string was short
- while (ii < 16) {
- buf[i + ii++] = 0;
- }
-
- return buf;
- }
-
- // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
- function unparse(buf, offset) {
- var i = offset || 0, bth = _byteToHex;
- return bth[buf[i++]] + bth[buf[i++]] +
- bth[buf[i++]] + bth[buf[i++]] + '-' +
- bth[buf[i++]] + bth[buf[i++]] + '-' +
- bth[buf[i++]] + bth[buf[i++]] + '-' +
- bth[buf[i++]] + bth[buf[i++]] + '-' +
- bth[buf[i++]] + bth[buf[i++]] +
- bth[buf[i++]] + bth[buf[i++]] +
- bth[buf[i++]] + bth[buf[i++]];
- }
-
- // **`v1()` - Generate time-based UUID**
- //
- // Inspired by https://github.com/LiosK/UUID.js
- // and http://docs.python.org/library/uuid.html
-
- // random #'s we need to init node and clockseq
- var _seedBytes = _rng();
-
- // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
- var _nodeId = [
- _seedBytes[0] | 0x01,
- _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
- ];
-
- // Per 4.2.2, randomize (14 bit) clockseq
- var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
-
- // Previous uuid creation time
- var _lastMSecs = 0, _lastNSecs = 0;
-
- // See https://github.com/broofa/node-uuid for API details
- function v1(options, buf, offset) {
- var i = buf && offset || 0;
- var b = buf || [];
-
- options = options || {};
-
- var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
-
- // UUID timestamps are 100 nano-second units since the Gregorian epoch,
- // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
- // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
- // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
- var msecs = options.msecs != null ? options.msecs : new Date().getTime();
-
- // Per 4.2.1.2, use count of uuid's generated during the current clock
- // cycle to simulate higher resolution clock
- var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
-
- // Time since last uuid creation (in msecs)
- var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
- // Per 4.2.1.2, Bump clockseq on clock regression
- if (dt < 0 && options.clockseq == null) {
- clockseq = clockseq + 1 & 0x3fff;
- }
-
- // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
- // time interval
- if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
- nsecs = 0;
- }
-
- // Per 4.2.1.2 Throw error if too many uuids are requested
- if (nsecs >= 10000) {
- throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
- }
-
- _lastMSecs = msecs;
- _lastNSecs = nsecs;
- _clockseq = clockseq;
-
- // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
- msecs += 12219292800000;
-
- // `time_low`
- var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
- b[i++] = tl >>> 24 & 0xff;
- b[i++] = tl >>> 16 & 0xff;
- b[i++] = tl >>> 8 & 0xff;
- b[i++] = tl & 0xff;
-
- // `time_mid`
- var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
- b[i++] = tmh >>> 8 & 0xff;
- b[i++] = tmh & 0xff;
-
- // `time_high_and_version`
- b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
- b[i++] = tmh >>> 16 & 0xff;
-
- // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
- b[i++] = clockseq >>> 8 | 0x80;
-
- // `clock_seq_low`
- b[i++] = clockseq & 0xff;
-
- // `node`
- var node = options.node || _nodeId;
- for (var n = 0; n < 6; n++) {
- b[i + n] = node[n];
- }
-
- return buf ? buf : unparse(b);
- }
-
- // **`v4()` - Generate random UUID**
-
- // See https://github.com/broofa/node-uuid for API details
- function v4(options, buf, offset) {
- // Deprecated - 'format' argument, as supported in v1.2
- var i = buf && offset || 0;
-
- if (typeof(options) == 'string') {
- buf = options == 'binary' ? new BufferClass(16) : null;
- options = null;
- }
- options = options || {};
-
- var rnds = options.random || (options.rng || _rng)();
-
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
- rnds[6] = (rnds[6] & 0x0f) | 0x40;
- rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
- // Copy bytes to buffer, if provided
- if (buf) {
- for (var ii = 0; ii < 16; ii++) {
- buf[i + ii] = rnds[ii];
- }
- }
-
- return buf || unparse(rnds);
- }
-
- // Export public API
- var uuid = v4;
- uuid.v1 = v1;
- uuid.v4 = v4;
- uuid.parse = parse;
- uuid.unparse = unparse;
- uuid.BufferClass = BufferClass;
-
- // Export RNG options
- uuid.mathRNG = mathRNG;
- uuid.nodeRNG = nodeRNG;
- uuid.whatwgRNG = whatwgRNG;
-
- if (typeof(module) != 'undefined') {
- // Play nice with node.js
- module.exports = uuid;
- } else {
- // Play nice with browsers
- var _previousRoot = _global.uuid;
-
- // **`noConflict()` - (browser only) to reset global 'uuid' var**
- uuid.noConflict = function() {
- _global.uuid = _previousRoot;
- return uuid;
- }
- _global.uuid = uuid;
- }
-}());
```javascript
var RegClient = require('npm-registry-client')
-var client = new RegClient(options)
+var client = new RegClient(config)
client.get("npm", "latest", 1000, function (er, data, raw, res) {
// error is an error if there was a problem.
})
```
-# Options
+# Configuration
+
+This program is designed to work with
+[npmconf](https://npmjs.org/package/npmconf), but you can also pass in
+a plain-jane object with the appropriate configs, and it'll shim it
+for you. Any configuration thingie that has get/set/del methods will
+also be accepted.
* `registry` **Required** {String} URL to the registry
* `cache` **Required** {String} Path to the cache folder
-* `alwaysAuth` {Boolean} Auth even for GET requests.
+* `always-auth` {Boolean} Auth even for GET requests.
* `auth` {String} A base64-encoded `username:password`
* `email` {String} User's email address
* `tag` {String} The default tag to use when publishing new packages.
Default = `"latest"`
* `ca` {String} Cerficate signing authority certificates to trust.
-* `strictSSL` {Boolean} Whether or not to be strict with SSL
+* `strict-ssl` {Boolean} Whether or not to be strict with SSL
certificates. Default = `true`
-* `userAgent` {String} User agent header to send. Default =
+* `user-agent` {String} User agent header to send. Default =
`"node/{process.version}"`
* `log` {Object} The logger to use. Defaults to `require("npmlog")` if
that works, otherwise logs are disabled.
-* `retries` {Number} Number of times to retry on GET failures.
+* `fetch-retries` {Number} Number of times to retry on GET failures.
Default=2
-* `retryFactor` {Number} `factor` setting for `node-retry`. Default=10
-* `retryMinTimeout` {Number} `minTimeout` setting for `node-retry`.
+* `fetch-retry-factor` {Number} `factor` setting for `node-retry`. Default=10
+* `fetch-retry-mintimeout` {Number} `minTimeout` setting for `node-retry`.
Default=10000 (10 seconds)
-* `retryMaxTimeout` {Number} `maxTimeout` setting for `node-retry`.
+* `fetch-retry-maxtimeout` {Number} `maxTimeout` setting for `node-retry`.
Default=60000 (60 seconds)
+* `proxy` {URL} The url to proxy requests through.
+* `https-proxy` {URL} The url to proxy https requests through.
+ Defaults to be the same as `proxy` if unset.
+* `_auth` {String} The base64-encoded authorization header.
+* `username` `_password` {String} Username/password to use to generate
+ `_auth` if not supplied.
+* `_token` {Object} A token for use with
+ [couch-login](https://npmjs.org/package/couch-login)
# client.request(method, where, [what], [etag], [nofollow], cb)
function noop () {}
-function RegClient (options) {
+function RegClient (conf) {
+ // accept either a plain-jane object, or a npmconf object
+ // with a "get" method.
+ if (typeof conf.get !== 'function') {
+ var data = conf
+ conf = { get: function (k) { return data[k] }
+ , set: function (k, v) { data[k] = v }
+ , del: function (k) { delete data[k] } }
+ }
+
+ this.conf = conf
+
// if provided, then the registry needs to be a url.
// if it's not provided, then we're just using the cache only.
- var registry = options.registry
+ var registry = conf.get('registry')
if (registry) {
registry = url.parse(registry)
if (!registry.protocol) throw new Error(
'Invalid registry: ' + registry.url)
- this.registry = registry.href
- if (this.registry.slice(-1) !== '/') {
- this.registry += '/'
+ registry = registry.href
+ if (registry.slice(-1) !== '/') {
+ registry += '/'
}
+ this.conf.set('registry', registry)
} else {
- this.registry = null
+ registry = null
}
- this.retries = options.retries || 2
- this.retryFactor = options.retryFactor || 10
- this.retryMinTimeout = options.retryMinTimeout || 10000
- this.retryMaxTimeout = options.retryMaxTimeout || 60000
-
- this.cache = options.cache
- if (!this.cache) throw new Error("Cache dir is required")
-
- this.alwaysAuth = options.alwaysAuth || false
+ if (!conf.get('cache')) throw new Error("Cache dir is required")
- this.auth = options.auth || null
- if (this.auth) {
- var a = new Buffer(this.auth, "base64").toString()
- a = a.split(":")
- this.username = a.shift()
- this.password = a.join(":")
- } else {
- this.username = options.username
- this.password = options.password
-
- // if username and password are set, but auth isn't, use them.
- if (this.username && this.password) {
- var a = this.username + ":" + this.password
- this.auth = new Buffer(a, "utf8").toString("base64")
- }
- }
-
- if (this.auth && !this.alwaysAuth && this.registry) {
+ var auth = this.conf.get('_auth')
+ var alwaysAuth = this.conf.get('always-auth')
+ if (auth && !alwaysAuth && registry) {
// if we're always authing, then we just send the
// user/pass on every thing. otherwise, create a
// session, and use that.
- this.token = options.token
- this.couchLogin = new CouchLogin(this.registry, this.token)
- this.couchLogin.proxy = this.proxy
- }
-
- this.email = options.email || null
- this.defaultTag = options.tag || "latest"
-
- this.ca = options.ca || null
-
- this.strictSSL = options.strictSSL
- if (this.strictSSL === undefined) this.strictSSL = true
-
- this.userAgent = options.userAgent
- if (this.userAgent === undefined) {
- this.userAgent = 'node/' + process.version
+ var token = this.conf.get('_token')
+ this.couchLogin = new CouchLogin(registry, token)
+ this.couchLogin.proxy = this.conf.get('proxy')
}
- this.cacheMin = options.cacheMin || 0
- this.cacheMax = options.cacheMax || Infinity
-
- this.proxy = options.proxy
- this.httpsProxy = options.httpsProxy || options.proxy
-
- this.log = options.log || npmlog
+ this.log = conf.log || conf.get('log') || npmlog
}
require('fs').readdirSync(__dirname + "/lib").forEach(function (f) {
-
module.exports = adduser
-var uuid = require("node-uuid")
- , crypto
-
-try {
-} catch (ex) {}
+var crypto = require('crypto')
function sha (s) {
return crypto.createHash("sha1").update(s).digest("hex")
}
function adduser (username, password, email, cb) {
- if (!crypto) crypto = require("crypto")
password = ("" + (password || "")).trim()
if (!password) return cb(new Error("No password supplied."))
"Sorry, ':' chars are not allowed in passwords.\n"+
"See <https://issues.apache.org/jira/browse/COUCHDB-969> for why."))
- var salt = uuid()
+ var salt = crypto.randomBytes(30).toString('hex')
, userobj =
{ name : username
, salt : salt
// pluck off any other username/password/token. it needs to be the
// same as the user we're becoming now. replace them on error.
- var pre = { username: this.username
- , password: this.password
- , auth: this.auth
- , token: this.token }
-
- this.token = null
+ var pre = { username: this.conf.get('username')
+ , password: this.conf.get('_password')
+ , auth: this.conf.get('_auth')
+ , token: this.conf.get('_token') }
+
+ this.conf.del('_token')
+ this.conf.del('username')
+ this.conf.del('_auth')
+ this.conf.del('_password')
if (this.couchLogin) {
this.couchLogin.token = null
}
- this.username = null
- this.password = null
- this.auth = null
cb = done.call(this, cb, pre)
, function (error, data, json, response) {
// if it worked, then we just created a new user, and all is well.
// but if we're updating a current record, then it'll 409 first
- if (error && !this.auth) {
+ if (error && !this.conf.get('_auth')) {
// must be trying to re-auth on a new machine.
// use this info as auth
var b = new Buffer(username + ":" + password)
- this.auth = b.toString("base64")
- this.username = username
- this.password = password
+ this.conf.set('_auth', b.toString("base64"))
+ this.conf.set('username', username)
+ this.conf.set('_password', password)
}
if (!error || !response || response.statusCode !== 409) {
}
// there was some kind of error, re-instate previous auth/token/etc.
- this.token = pre.token
+ this.conf.set('_token', pre.token)
if (this.couchLogin) {
- this.couchLogin.token = this.token
+ this.couchLogin.token = pre.token
if (this.couchLogin.tokenSet) {
this.couchLogin.tokenSet(pre.token)
}
}
- this.username = pre.username
- this.password = pre.password
- this.auth = pre.auth
+ this.conf.set('username', pre.username)
+ this.conf.set('_password', pre.password)
+ this.conf.set('_auth', pre.auth)
this.log.verbose("adduser", "back", [error, data, json])
if (!error) {
if (typeof cb !== "function") cb = timeout, timeout = -1
if (typeof cb !== "function") cb = version, version = null
- timeout = Math.min(timeout, this.cacheMax)
- timeout = Math.max(timeout, this.cacheMin)
+ timeout = Math.min(timeout, this.conf.get('cache-max') || 0)
+ timeout = Math.max(timeout, this.conf.get('cache-min') || Infinity)
- if (!this.registry) timeout = Infinity
+ if (!this.conf.get('registry')) timeout = Infinity
if ( process.env.COMP_CWORD !== undefined
&& process.env.COMP_LINE !== undefined
return requestAll.call(this, cb)
}
- var cache = path.join(this.cache, uri, ".cache.json")
+ var cache = path.join(this.conf.get('cache'), uri, ".cache.json")
fs.stat(cache, function (er, stat) {
if (!er) fs.readFile(cache, function (er, data) {
try { data = JSON.parse(data) }
}
function requestAll (cb) {
- var cache = path.join(this.cache, "/-/all", ".cache.json")
+ var cache = path.join(this.conf.get('cache'), "/-/all", ".cache.json")
- mkdir(path.join(this.cache, "-", "all"), function (er) {
+ mkdir(path.join(this.conf.get('cache'), "-", "all"), function (er) {
fs.readFile(cache, function (er, data) {
if (er) return requestAll_.call(this, 0, {}, cb)
try {
uri = "/-/all"
}
- var cache = path.join(this.cache, "-/all", ".cache.json")
+ var cache = path.join(this.conf.get('cache'), "-/all", ".cache.json")
this.request('GET', uri, function (er, updates, _, res) {
if (er) return cb(er, data)
var headers = res.headers
}
function saveToCache (cache, data, saved) {
- if (this.cacheStat) {
- var cs = this.cacheStat
+ if (this._cacheStat) {
+ var cs = this._cacheStat
return saveToCache_.call(this, cache, data, cs.uid, cs.gid, saved)
}
- fs.stat(this.cache, function (er, st) {
+ fs.stat(this.conf.get('cache'), function (er, st) {
if (er) {
return fs.stat(process.env.HOME || "", function (er, st) {
// if this fails, oh well.
if (er) return saved()
- this.cacheStat = st
+ this._cacheStat = st
return saveToCache.call(this, cache, data, saved)
}.bind(this))
}
- this.cacheStat = st || { uid: null, gid: null }
+ this._cacheStat = st || { uid: null, gid: null }
return saveToCache.call(this, cache, data, saved)
}.bind(this))
}
function publish (data, tarball, cb) {
- if (!this.email || !this.auth || !this.username) {
- return cb(new Error("auth and email required for publishing"))
+ var email = this.conf.get('email')
+ var auth = this.conf.get('_auth')
+ var username = this.conf.get('username')
+
+ if (!email || !auth || !username) {
+ var er = new Error("auth and email required for publishing")
+ er.code = 'ENEEDAUTH'
+ return cb(er)
}
// add the dist-url to the data, pointing at the tarball.
// if the {version} is already there, then fail.
// then:
// PUT the data to {config.registry}/{data.name}/{data.version}
- var registry = this.registry
+ var registry = this.conf.get('registry')
var fullData =
{ _id : data.name
, versions : {}
, readme: data.readme || ""
, maintainers :
- [ { name : this.username
- , email : this.email
+ [ { name : username
+ , email : email
}
]
}
var dataURI = encodeURIComponent(data.name)
+ "/" + encodeURIComponent(data.version)
- var tag = data.tag || this.defaultTag || "latest"
+ var tag = data.tag || this.conf.get('tag') || "latest"
dataURI += "/-tag/" + tag
// let's see what versions are already published.
if (typeof cb_ !== "function") cb_ = etag, etag = null
if (typeof cb_ !== "function") cb_ = what, what = null
- if (!this.registry) return cb(new Error(
+ var registry = this.conf.get('registry')
+ if (!registry) return cb(new Error(
"No registry url provided: " + method + " " + where))
// Since there are multiple places where an error could occur,
return cb(new Error("favicon.ico isn't a package, it's a picture."))
}
- var registry = this.registry
-
var adduserChange = /^\/?-\/user\/org\.couchdb\.user:([^\/]+)\/-rev/
, adduserNew = /^\/?-\/user\/org\.couchdb\.user:([^\/]+)/
, nu = where.match(adduserNew)
, uc = where.match(adduserChange)
- , isUpload = what || this.alwaysAuth
+ , isUpload = what || this.conf.get('always-auth')
, isDel = method === "DELETE"
, authRequired = isUpload && !nu || uc || isDel
}
var remote = url.parse(where)
- , auth = this.auth
+ , auth = this.conf.get('_auth')
- if (authRequired && !this.alwaysAuth) {
+ if (authRequired && !this.conf.get('always-auth')) {
var couch = this.couchLogin
- , token = couch && (this.token || couch.token)
+ , token = couch && (this.conf.get('_token') || couch.token)
, validToken = token && couch.valid(token)
if (!validToken) token = null
- else this.token = token
+ else this.conf.set('_token', token)
if (couch && !token) {
// login to get a valid token
- var a = { name: this.username, password: this.password }
+ var a = { name: this.conf.get('username'),
+ password: this.conf.get('_password') }
var args = arguments
return this.couchLogin.login(a, function (er, cr, data) {
if (er || !couch.valid(couch.token)) {
er = er || new Error('login error')
return cb(er, cr, data)
}
- this.token = this.couchLogin.token
- return regRequest.call(this, method, where, what, etag, nofollow, cb_)
+ this.conf.set('_token', this.couchLogin.token)
+ return regRequest.call(this,
+ method, where, what,
+ etag, nofollow, cb_)
}.bind(this))
}
}
// Tuned to spread 3 attempts over about a minute.
// See formula at <https://github.com/tim-kos/node-retry>.
var operation = retry.operation({
- retries: this.retries,
- factor: this.retryFactor,
- minTimeout: this.retryMinTimeout,
- maxTimeout: this.retryMaxTimeout
+ retries: this.conf.get('fetch-retries') || 2,
+ factor: this.conf.get('fetch-retry-factor'),
+ minTimeout: this.conf.get('fetch-retry-mintimeout') || 10000,
+ maxTimeout: this.conf.get('fetch-retry-maxtimeout') || 60000
})
+
var self = this
operation.attempt(function (currentAttempt) {
self.log.info("retry", "registry request attempt " + currentAttempt
var timeout = statusCode === 408
var serverError = statusCode >= 500
var statusRetry = !statusCode || timeout || serverError
- if (reauth && this.auth && this.token) {
- this.token = null
+ if (reauth && this.conf.get('_auth') && this.conf.get('_token')) {
+ this.conf.del('_token')
this.couchLogin.token = null
return regRequest.call(this, method, where, what, etag, nofollow, cb_)
}
cb_.apply(null, arguments)
}
+ var strict = this.conf.get('strict-ssl')
+ if (strict === undefined) strict = true
var opts = { url: remote
, method: method
- , ca: this.ca
- , strictSSL: this.strictSSL }
+ , ca: this.conf.get('ca')
+ , strictSSL: strict }
, headers = opts.headers = {}
if (etag) {
this.log.verbose("etag", etag)
headers.accept = "application/json"
- headers["user-agent"] = this.userAgent
+ headers["user-agent"] = this.conf.get('user-agent') ||
+ 'node/' + process.version
- opts.proxy = remote.protocol === "https:"
- ? this.httpsProxy : this.proxy
+ var p = this.conf.get('proxy')
+ var sp = this.conf.get('https-proxy') || p
+ opts.proxy = remote.protocol === "https:" ? sp : p
// figure out wth 'what' is
if (what) {
, caches = p.map(function (part) {
return _ = path.join(_, part)
}).map(function (cache) {
- return path.join(this.cache, cache, ".cache.json")
+ return path.join(this.conf.get('cache'), cache, ".cache.json")
}, this)
// if the method is DELETE, then also remove the thing itself.
// That's what you get for deleting stuff. Don't do that.
if (method === "DELETE") {
p = p.slice(0, p.indexOf("-rev"))
- caches.push(path.join(this.cache, p.join("/")))
+ caches.push(path.join(this.conf.get('cache'), p.join("/")))
}
asyncMap(caches, rm, function () {})
module.exports = star
function star (package, starred, cb) {
- if (!this.username) return cb(new Error(
+ if (!this.conf.get('username')) return cb(new Error(
"Must be logged in to star/unstar packages"))
var users = {}
if (starred) {
this.log.info("starring", fullData._id)
- fullData.users[this.username] = true
+ fullData.users[this.conf.get('username')] = true
this.log.verbose("starring", fullData)
} else {
- delete fullData.users[this.username]
+ delete fullData.users[this.conf.get('username')]
this.log.info("unstarring", fullData._id)
this.log.verbose("unstarring", fullData)
}
},
"name": "npm-registry-client",
"description": "Client for the npm registry",
- "version": "0.1.4",
+ "version": "0.2.5",
"repository": {
"url": "git://github.com/isaacs/npm-registry-client"
},
"test": "tap test/*.js"
},
"dependencies": {
- "node-uuid": "~1.3.3",
"request": "~2.9.202",
"graceful-fs": "~1.1.8",
"semver": "~1.0.14",
"npmlog": ""
},
"license": "BSD",
- "readme": "# npm-registry-client\n\nThe code that npm uses to talk to the registry.\n\nIt handles all the caching and HTTP calls.\n\n## Usage\n\n```javascript\nvar RegClient = require('npm-registry-client')\nvar client = new RegClient(options)\n\nclient.get(\"npm\", \"latest\", 1000, function (er, data, raw, res) {\n // error is an error if there was a problem.\n // data is the parsed data object\n // raw is the json string\n // res is the response from couch\n})\n```\n\n# Options\n\n* `registry` **Required** {String} URL to the registry\n* `cache` **Required** {String} Path to the cache folder\n* `alwaysAuth` {Boolean} Auth even for GET requests.\n* `auth` {String} A base64-encoded `username:password`\n* `email` {String} User's email address\n* `tag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `ca` {String} Cerficate signing authority certificates to trust.\n* `strictSSL` {Boolean} Whether or not to be strict with SSL\n certificates. Default = `true`\n* `userAgent` {String} User agent header to send. Default =\n `\"node/{process.version}\"`\n* `log` {Object} The logger to use. Defaults to `require(\"npmlog\")` if\n that works, otherwise logs are disabled.\n* `retries` {Number} Number of times to retry on GET failures.\n Default=2\n* `retryFactor` {Number} `factor` setting for `node-retry`. Default=10\n* `retryMinTimeout` {Number} `minTimeout` setting for `node-retry`.\n Default=10000 (10 seconds)\n* `retryMaxTimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default=60000 (60 seconds)\n\n# client.request(method, where, [what], [etag], [nofollow], cb)\n\n* `method` {String} HTTP method\n* `where` {String} Path to request on the server\n* `what` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON.\n* `etag` {String} The cached ETag\n* `nofollow` {Boolean} Prevent following 302/301 responses\n* `cb` {Function}\n * `error` {Error | null}\n * `data` {Object} the parsed data object\n * `raw` {String} the json\n * `res` {Response Object} response from couch\n\nMake a request to the registry. All the other methods are wrappers\naround this. one.\n\n# client.adduser(username, password, email, cb)\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `cb` {Function}\n\nAdd a user account to the registry, or verify the credentials.\n\n# client.get(url, [timeout], [nofollow], [staleOk], cb)\n\n* `url` {String} The url path to fetch\n* `timeout` {Number} Number of seconds old that a cached copy must be\n before a new request will be made.\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `staleOk` {Boolean} If there's cached data available, then return that\n to the callback quickly, and update the cache the background.\n\nFetches data from the registry via a GET request, saving it in\nthe cache folder with the ETag.\n\n# client.publish(data, tarball, [readme], cb)\n\n* `data` {Object} Package data\n* `tarball` {String | Stream} Filename or stream of the package tarball\n* `readme` {String} Contents of the README markdown file\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder. However, it\ncan accept a gzipped tar stream or a filename to a tarball.\n\n# client.star(package, starred, cb)\n\n* `package` {String} Name of the package to star\n* `starred` {Boolean} True to star the package, false to unstar it.\n* `cb` {Function}\n\nStar or unstar a package.\n\nNote that the user does not have to be the package owner to star or\nunstar a package, though other writes do require that the user be the\npackage owner.\n\n# client.tag(project, version, tag, cb)\n\n* `project` {String} Project name\n* `version` {String} Version to tag\n* `tag` {String} Tag name to apply\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag`\nwill fetch the specified version.\n\n# client.unpublish(name, [ver], cb)\n\n* `name` {String} package name\n* `ver` {String} version to unpublish. Leave blank to unpublish all\n versions.\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When\nthe last version us unpublished, the entire document is removed from the\ndatabase.\n\n# client.upload(where, file, [etag], [nofollow], cb)\n\n* `where` {String} URL path to upload to\n* `file` {String | Stream} Either the filename or a readable stream\n* `etag` {String} Cache ETag\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `cb` {Function}\n\nUpload an attachment. Mostly used by `client.publish()`.\n",
- "_id": "npm-registry-client@0.1.4",
- "_from": "npm-registry-client@latest"
+ "readme": "# npm-registry-client\n\nThe code that npm uses to talk to the registry.\n\nIt handles all the caching and HTTP calls.\n\n## Usage\n\n```javascript\nvar RegClient = require('npm-registry-client')\nvar client = new RegClient(config)\n\nclient.get(\"npm\", \"latest\", 1000, function (er, data, raw, res) {\n // error is an error if there was a problem.\n // data is the parsed data object\n // raw is the json string\n // res is the response from couch\n})\n```\n\n# Configuration\n\nThis program is designed to work with\n[npmconf](https://npmjs.org/package/npmconf), but you can also pass in\na plain-jane object with the appropriate configs, and it'll shim it\nfor you. Any configuration thingie that has get/set/del methods will\nalso be accepted.\n\n* `registry` **Required** {String} URL to the registry\n* `cache` **Required** {String} Path to the cache folder\n* `always-auth` {Boolean} Auth even for GET requests.\n* `auth` {String} A base64-encoded `username:password`\n* `email` {String} User's email address\n* `tag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `ca` {String} Cerficate signing authority certificates to trust.\n* `strict-ssl` {Boolean} Whether or not to be strict with SSL\n certificates. Default = `true`\n* `user-agent` {String} User agent header to send. Default =\n `\"node/{process.version}\"`\n* `log` {Object} The logger to use. Defaults to `require(\"npmlog\")` if\n that works, otherwise logs are disabled.\n* `fetch-retries` {Number} Number of times to retry on GET failures.\n Default=2\n* `fetch-retry-factor` {Number} `factor` setting for `node-retry`. Default=10\n* `fetch-retry-mintimeout` {Number} `minTimeout` setting for `node-retry`.\n Default=10000 (10 seconds)\n* `fetch-retry-maxtimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default=60000 (60 seconds)\n* `proxy` {URL} The url to proxy requests through.\n* `https-proxy` {URL} The url to proxy https requests through.\n Defaults to be the same as `proxy` if unset.\n* `_auth` {String} The base64-encoded authorization header.\n* `username` `_password` {String} Username/password to use to generate\n `_auth` if not supplied.\n* `_token` {Object} A token for use with\n [couch-login](https://npmjs.org/package/couch-login)\n\n# client.request(method, where, [what], [etag], [nofollow], cb)\n\n* `method` {String} HTTP method\n* `where` {String} Path to request on the server\n* `what` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON.\n* `etag` {String} The cached ETag\n* `nofollow` {Boolean} Prevent following 302/301 responses\n* `cb` {Function}\n * `error` {Error | null}\n * `data` {Object} the parsed data object\n * `raw` {String} the json\n * `res` {Response Object} response from couch\n\nMake a request to the registry. All the other methods are wrappers\naround this. one.\n\n# client.adduser(username, password, email, cb)\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `cb` {Function}\n\nAdd a user account to the registry, or verify the credentials.\n\n# client.get(url, [timeout], [nofollow], [staleOk], cb)\n\n* `url` {String} The url path to fetch\n* `timeout` {Number} Number of seconds old that a cached copy must be\n before a new request will be made.\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `staleOk` {Boolean} If there's cached data available, then return that\n to the callback quickly, and update the cache the background.\n\nFetches data from the registry via a GET request, saving it in\nthe cache folder with the ETag.\n\n# client.publish(data, tarball, [readme], cb)\n\n* `data` {Object} Package data\n* `tarball` {String | Stream} Filename or stream of the package tarball\n* `readme` {String} Contents of the README markdown file\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder. However, it\ncan accept a gzipped tar stream or a filename to a tarball.\n\n# client.star(package, starred, cb)\n\n* `package` {String} Name of the package to star\n* `starred` {Boolean} True to star the package, false to unstar it.\n* `cb` {Function}\n\nStar or unstar a package.\n\nNote that the user does not have to be the package owner to star or\nunstar a package, though other writes do require that the user be the\npackage owner.\n\n# client.tag(project, version, tag, cb)\n\n* `project` {String} Project name\n* `version` {String} Version to tag\n* `tag` {String} Tag name to apply\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag`\nwill fetch the specified version.\n\n# client.unpublish(name, [ver], cb)\n\n* `name` {String} package name\n* `ver` {String} version to unpublish. Leave blank to unpublish all\n versions.\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When\nthe last version us unpublished, the entire document is removed from the\ndatabase.\n\n# client.upload(where, file, [etag], [nofollow], cb)\n\n* `where` {String} URL path to upload to\n* `file` {String | Stream} Either the filename or a readable stream\n* `etag` {String} Cache ETag\n* `nofollow` {Boolean} Do not follow 301/302 responses\n* `cb` {Function}\n\nUpload an attachment. Mostly used by `client.publish()`.\n",
+ "_id": "npm-registry-client@0.2.5",
+ "_from": "npm-registry-client@~0.2.4"
}
name: 'some-package',
version: '1.2.3' }
var client = new RC({
- retries: 6
- , retryMinTimeout: 10
- , retryMaxTimeout: 100
+ 'fetch-retries': 6
+ , 'fetch-retry-mintimeout': 10
+ , 'fetch-retry-maxtimeout': 100
, cache: __dirname + '/fixtures/cache'
, registry: 'http://localhost:' + server.port })
var nopt = require('nopt')
var ini = require('ini')
var Octal = configDefs.Octal
+var mkdirp = require('mkdirp')
exports.load = load
exports.Conf = Conf
then = then.bind(this)
done = done.bind(this)
this._saving ++
+
var mode = where === 'user' ? 0600 : 0666
if (!data.trim())
fs.unlink(target.path, done)
else {
- fs.writeFile(target.path, data, 'utf8', function (er) {
+ mkdirp(path.dirname(target.path), function (er) {
if (er)
return then(er)
- if (where === 'user' && myUid && myGid)
- fs.chown(target.path, +myUid, +myGid, then)
- else
- then()
- }.bind(this))
+ fs.writeFile(target.path, data, 'utf8', function (er) {
+ if (er)
+ return then(er)
+ if (where === 'user' && myUid && myGid)
+ fs.chown(target.path, +myUid, +myGid, then)
+ else
+ then()
+ })
+ })
}
function then (er) {
{
"name": "npmconf",
- "version": "0.0.6",
+ "version": "0.0.8",
"description": "The config thing npm uses",
"main": "npmconf.js",
"directories": {
"config-chain": "~1.1.1",
"inherits": "~1.0.0",
"once": "~1.1.1",
+ "mkdirp": "~0.3.3",
+ "osenv": "0.0.3",
"nopt": "~2.0.0"
},
"devDependencies": {},
"nopt": "~2.0.0"
},
"readme": "# npmconf\n\nThe config thing npm uses\n\nIf you are interested in interacting with the config settings that npm\nuses, then use this module.\n\nHowever, if you are writing a new Node.js program, and want\nconfiguration functionality similar to what npm has, but for your\nown thing, then I'd recommend using [rc](https://github.com/dominictarr/rc),\nwhich is probably what you want.\n\nIf I were to do it all over again, that's what I'd do for npm. But,\nalas, there are many systems depending on many of the particulars of\nnpm's configuration setup, so it's not worth the cost of changing.\n\n## USAGE\n\n```javascript\nvar npmconf = require('npmconf')\n\n// pass in the cli options that you read from the cli\n// or whatever top-level configs you want npm to use for now.\nnpmconf.load({some:'configs'}, function (er, conf) {\n // do stuff with conf\n conf.get('some', 'cli') // 'configs'\n conf.get('username') // 'joebobwhatevers'\n conf.set('foo', 'bar', 'user')\n conf.save('user', function (er) {\n // foo = bar is now saved to ~/.npmrc or wherever\n })\n})\n```\n",
- "_id": "npmconf@0.0.6",
- "_from": "npmconf@latest"
+ "_id": "npmconf@0.0.8",
+ "_from": "npmconf@~0.0.6"
}
{
"name": "read-installed",
"description": "Read all the installed packages in a folder, and return a tree structure with all the data.",
- "version": "0.0.1",
+ "version": "0.0.2",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/read-installed"
"url": "http://blog.izs.me/"
},
"readme": "# read-installed\n\nRead all the installed packages in a folder, and return a tree\nstructure with all the data.\n\nnpm uses this.\n\n## Usage\n\n```javascript\nvar readInstalled = require(\"read-installed\")\n// depth is optional, defaults to Infinity\nreadInstalled(folder, depth, function (er, data) {\n ...\n})\n```\n",
- "_id": "read-installed@0.0.1",
- "_from": "read-installed"
+ "_id": "read-installed@0.0.2",
+ "_from": "read-installed@0"
}
+found.path+",\nwhich is version "+found.version
)
found.invalid = true
+ } else {
+ found.extraneous = false
}
deps[d] = found
}
{
"name": "read-package-json",
- "version": "0.1.3",
+ "version": "0.1.4",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"graceful-fs": "~1.1.8"
},
"readme": "# read-package-json\n\nThis is the thing that npm uses to read package.json files. It\nvalidates some stuff, and loads some default things.\n\nIt keeps a cache of the files you've read, so that you don't end\nup reading the same package.json file multiple times.\n\nNote that if you just want to see what's literally in the package.json\nfile, you can usually do `var data = require('some-module/package.json')`.\n\nThis module is basically only needed by npm, but it's handy to see what\nnpm will see when it looks at your package.\n\n## Usage\n\n```javascript\nvar readJson = require('read-package-json')\n\nreadJson('/path/to/package.json', function (er, data) {\n if (er) {\n console.error(\"There was an error reading the file\")\n return\n }\n\n console.error('the package data is', data)\n}\n```\n\n## readJson(file, cb)\n\n* `file` {String} The path to the package.json file\n* `cb` {Function}\n\nReads the JSON file and does the things.\n\n## `package.json` Fields\n\nSee `man 5 package.json` or `npm help json`.\n\n## readJson.log\n\nBy default this is a reference to the `npmlog` module. But if that\nmodule can't be found, then it'll be set to just a dummy thing that does\nnothing.\n\nReplace with your own `{log,warn,error}` object for fun loggy time.\n\n## readJson.extras(file, data, cb)\n\nRun all the extra stuff relative to the file, with the parsed data.\n\nModifies the data as it does stuff. Calls the cb when it's done.\n\n## readJson.extraSet = [fn, fn, ...]\n\nArray of functions that are called by `extras`. Each one receives the\narguments `fn(file, data, cb)` and is expected to call `cb(er, data)`\nwhen done or when an error occurs.\n\nOrder is indeterminate, so each function should be completely\nindependent.\n\nMix and match!\n\n## readJson.cache\n\nThe `lru-cache` object that readJson uses to not read the same file over\nand over again. See\n[lru-cache](https://github.com/isaacs/node-lru-cache) for details.\n\n## Other Relevant Files Besides `package.json`\n\nSome other files have an effect on the resulting data object, in the\nfollowing ways:\n\n### `README?(.*)`\n\nIf there is a `README` or `README.*` file present, then npm will attach\na `readme` field to the data with the contents of this file.\n\nOwing to the fact that roughly 100% of existing node modules have\nMarkdown README files, it will generally be assumed to be Markdown,\nregardless of the extension. Please plan accordingly.\n\n### `server.js`\n\nIf there is a `server.js` file, and there is not already a\n`scripts.start` field, then `scripts.start` will be set to `node\nserver.js`.\n\n### `AUTHORS`\n\nIf there is not already a `contributors` field, then the `contributors`\nfield will be set to the contents of the `AUTHORS` file, split by lines,\nand parsed.\n\n### `bindings.gyp`\n\nIf a bindings.gyp file exists, and there is not already a\n`scripts.install` field, then the `scripts.install` field will be set to\n`node-gyp rebuild`.\n\n### `wscript`\n\nIf a wscript file exists, and there is not already a `scripts.install`\nfield, then the `scripts.install` field will be set to `node-waf clean ;\nnode-waf configure build`.\n\nNote that the `bindings.gyp` file supercedes this, since node-waf has\nbeen deprecated in favor of node-gyp.\n\n### `index.js`\n\nIf the json file does not exist, but there is a `index.js` file\npresent instead, and that file has a package comment, then it will try\nto parse the package comment, and use that as the data instead.\n\nA package comment looks like this:\n\n```javascript\n/**package\n * { \"name\": \"my-bare-module\"\n * , \"version\": \"1.2.3\"\n * , \"description\": \"etc....\" }\n **/\n\n// or...\n\n/**package\n{ \"name\": \"my-bare-module\"\n, \"version\": \"1.2.3\"\n, \"description\": \"etc....\" }\n**/\n```\n\nThe important thing is that it starts with `/**package`, and ends with\n`**/`. If the package.json file exists, then the index.js is not\nparsed.\n\n### `{directories.man}/*.[0-9]`\n\nIf there is not already a `man` field defined as an array of files or a\nsingle file, and\nthere is a `directories.man` field defined, then that directory will\nbe searched for manpages.\n\nAny valid manpages found in that directory will be assigned to the `man`\narray, and installed in the appropriate man directory at package install\ntime, when installed globally on a Unix system.\n\n### `{directories.bin}/*`\n\nIf there is not already a `bin` field defined as a string filename or a\nhash of `<name> : <filename>` pairs, then the `directories.bin`\ndirectory will be searched and all the files within it will be linked as\nexecutables at install time.\n\nWhen installing locally, npm links bins into `node_modules/.bin`, which\nis in the `PATH` environ when npm runs scripts. When\ninstalling globally, they are linked into `{prefix}/bin`, which is\npresumably in the `PATH` environment variable.\n",
- "_id": "read-package-json@0.1.3",
- "_from": "read-package-json@~0.1.1"
+ "_id": "read-package-json@0.1.4",
+ "_from": "read-package-json@~0.1.3"
}
function mans_ (file, data, mans, cb) {
var m = data.directories && data.directories.man
data.man = mans.map(function (mf) {
- return path.resolve(m, mf)
+ return path.resolve(path.dirname(file), m, mf)
})
return cb(null, data)
}
If silent is true, and the input is a TTY, then read will set raw
mode, and read character by character.
+## COMPATIBILITY
+
+This module works sort of with node 0.6. It does not work with node
+versions less than 0.6. It is best on node 0.8.
+
+On node version 0.6, it will remove all listeners on the input
+stream's `data` and `keypress` events, because the readline module did
+not fully clean up after itself in that version of node, and did not
+make it possible to clean up after it in a way that has no potential
+for side effects.
+
+Additionally, some of the readline options (like `terminal`) will not
+function in versions of node before 0.8, because they were not
+implemented in the builtin readline module.
+
## CONTRIBUTING
Patches welcome.
var def = opts.default || ''
var terminal = !!(opts.terminal || output.isTTY)
var rlOpts = { input: input, output: output, terminal: terminal }
- var rl = readline.createInterface(rlOpts)
+
+ if (process.version.match(/^v0\.6/)) {
+ var rl = readline.createInterface(rlOpts.input, rlOpts.output)
+ } else {
+ var rl = readline.createInterface(rlOpts)
+ }
+
var prompt = (opts.prompt || '').trim() + ' '
var silent = opts.silent
var editDef = false
function done () {
called = true
rl.close()
+
+ if (process.version.match(/^v0\.6/)) {
+ rl.input.removeAllListeners('data')
+ rl.input.removeAllListeners('keypress')
+ rl.input.pause()
+ }
+
clearTimeout(timer)
output.mute()
output.end()
})
}
+Object.defineProperty(MuteStream.prototype, 'rows', {
+ get: function () {
+ return( this._dest ? this._dest.rows
+ : this._src ? this._src.rows
+ : undefined )
+ }, enumerable: true, configurable: true })
+
+Object.defineProperty(MuteStream.prototype, 'columns', {
+ get: function () {
+ return( this._dest ? this._dest.columns
+ : this._src ? this._src.columns
+ : undefined )
+ }, enumerable: true, configurable: true })
+
+
MuteStream.prototype.pipe = function (dest) {
this._dest = dest
return Stream.prototype.pipe.call(this, dest)
{
"name": "mute-stream",
- "version": "0.0.2",
+ "version": "0.0.3",
"main": "mute.js",
"directories": {
"test": "test"
"license": "BSD",
"description": "Bytes go in, but they don't come out (when muted).",
"readme": "# mute-stream\n\nBytes go in, but they don't come out (when muted).\n\nThis is a basic pass-through stream, but when muted, the bytes are\nsilently dropped, rather than being passed through.\n\n## Usage\n\n```javascript\nvar MuteStream = require('mute-stream')\n\nvar ms = new MuteStream(options)\n\nms.pipe(process.stdout)\nms.write('foo') // writes 'foo' to stdout\nms.mute()\nms.write('bar') // does not write 'bar'\nms.unmute()\nms.write('baz') // writes 'baz' to stdout\n\n// can also be used to mute incoming data\nvar ms = new MuteStream\ninput.pipe(ms)\n\nms.on('data', function (c) {\n console.log('data: ' + c)\n})\n\ninput.emit('data', 'foo') // logs 'foo'\nms.mute()\ninput.emit('data', 'bar') // does not log 'bar'\nms.unmute()\ninput.emit('data', 'baz') // logs 'baz'\n```\n\n## Options\n\nAll options are optional.\n\n* `replace` Set to a string to replace each character with the\n specified string when muted. (So you can show `****` instead of the\n password, for example.)\n\n## ms.mute()\n\nSet `muted` to `true`. Turns `.write()` into a no-op.\n\n## ms.unmute()\n\nSet `muted` to `false`\n\n## ms.isTTY\n\nTrue if the pipe destination is a TTY, or if the incoming pipe source is\na TTY.\n\n## Other stream methods...\n\nThe other standard readable and writable stream methods are all\navailable. The MuteStream object acts as a facade to its pipe source\nand destination.\n",
- "_id": "mute-stream@0.0.2",
- "dist": {
- "shasum": "75d4466df24a57e80fec806bda88561cd0560d2d"
- },
+ "_id": "mute-stream@0.0.3",
"_from": "mute-stream@~0.0.2"
}
tap.test('isTTY', function (t) {
var str = new PassThrough
str.isTTY = true
+ str.columns=80
+ str.rows=24
var ms = new MS
t.equal(ms.isTTY, false)
+ t.equal(ms.columns, undefined)
+ t.equal(ms.rows, undefined)
ms.pipe(str)
t.equal(ms.isTTY, true)
+ t.equal(ms.columns, 80)
+ t.equal(ms.rows, 24)
str.isTTY = false
t.equal(ms.isTTY, false)
+ t.equal(ms.columns, 80)
+ t.equal(ms.rows, 24)
str.isTTY = true
t.equal(ms.isTTY, true)
+ t.equal(ms.columns, 80)
+ t.equal(ms.rows, 24)
ms.isTTY = false
t.equal(ms.isTTY, false)
+ t.equal(ms.columns, 80)
+ t.equal(ms.rows, 24)
ms = new MS
t.equal(ms.isTTY, false)
{
"name": "read",
- "version": "1.0.3",
+ "version": "1.0.4",
"main": "lib/read.js",
"dependencies": {
"mute-stream": "~0.0.2"
"scripts": {
"test": "tap test/*.js"
},
- "readme": "## read\n\nFor reading user input from stdin.\n\nSimilar to the `readline` builtin's `question()` method, but with a\nfew more features.\n\n## USAGE\n\n```javascript\nvar read = require(\"read\")\nread(options, callback)\n```\n\nThe callback gets called with either the user input, or the default\nspecified, or an error, as `callback(error, result, isDefault)`\nnode style.\n\n## OPTIONS\n\nEvery option is optional.\n\n* `prompt` What to write to stdout before reading input.\n* `silent` Don't echo the output as the user types it.\n* `replace` Replace silenced characters with the supplied character value.\n* `timeout` Number of ms to wait for user input before giving up.\n* `default` The default value if the user enters nothing.\n* `edit` Allow the user to edit the default value.\n* `terminal` Treat the output as a TTY, whether it is or not.\n* `stdin` Readable stream to get input data from. (default `process.stdin`)\n* `stdout` Writeable stream to write prompts to. (default: `process.stdout`)\n\nIf silent is true, and the input is a TTY, then read will set raw\nmode, and read character by character.\n\n## CONTRIBUTING\n\nPatches welcome.\n",
- "_id": "read@1.0.3",
- "_from": "read@~1"
+ "readme": "## read\n\nFor reading user input from stdin.\n\nSimilar to the `readline` builtin's `question()` method, but with a\nfew more features.\n\n## USAGE\n\n```javascript\nvar read = require(\"read\")\nread(options, callback)\n```\n\nThe callback gets called with either the user input, or the default\nspecified, or an error, as `callback(error, result, isDefault)`\nnode style.\n\n## OPTIONS\n\nEvery option is optional.\n\n* `prompt` What to write to stdout before reading input.\n* `silent` Don't echo the output as the user types it.\n* `replace` Replace silenced characters with the supplied character value.\n* `timeout` Number of ms to wait for user input before giving up.\n* `default` The default value if the user enters nothing.\n* `edit` Allow the user to edit the default value.\n* `terminal` Treat the output as a TTY, whether it is or not.\n* `stdin` Readable stream to get input data from. (default `process.stdin`)\n* `stdout` Writeable stream to write prompts to. (default: `process.stdout`)\n\nIf silent is true, and the input is a TTY, then read will set raw\nmode, and read character by character.\n\n## COMPATIBILITY\n\nThis module works sort of with node 0.6. It does not work with node\nversions less than 0.6. It is best on node 0.8.\n\nOn node version 0.6, it will remove all listeners on the input\nstream's `data` and `keypress` events, because the readline module did\nnot fully clean up after itself in that version of node, and did not\nmake it possible to clean up after it in a way that has no potential\nfor side effects.\n\nAdditionally, some of the readline options (like `terminal`) will not\nfunction in versions of node before 0.8, because they were not\nimplemented in the builtin readline module.\n\n## CONTRIBUTING\n\nPatches welcome.\n",
+ "_id": "read@1.0.4",
+ "_from": "read@~1.0.3"
}
return child()
}
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+ CLOSE = 'exit'
+}
+
var spawn = require('child_process').spawn
tap.test('basic', function (t) {
console.error('result %j', c.toString())
})
- child.on('close', function () {
+ child.on(CLOSE, function () {
result = JSON.parse(result)
t.same(result, {"user":"a user","pass":"a password","verify":"a password","passMatch":true})
t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
return child()
}
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+ CLOSE = 'exit'
+}
+
var spawn = require('child_process').spawn
tap.test('defaults', function (t) {
console.error('result %j', c.toString())
})
- child.on('close', function () {
+ child.on(CLOSE, function () {
result = JSON.parse(result)
t.same(result, {"user":"test-user","pass":"test-pass","verify":"test-pass","passMatch":true})
t.equal(output, 'Username: (test-user) Password: (<default hidden>) Password again: (<default hidden>) ')
var tap = require('tap')
var read = require('../lib/read.js')
+var CLOSE = 'close'
+if (process.version.match(/^v0\.6/)) {
+ CLOSE = 'exit'
+}
+
if (process.argv[2] === 'child') {
return child()
}
output += c
console.error('' + c)
})
- child.on('close', function (c) {
+ child.on(CLOSE, function (c) {
t.equal(output, expect)
t.equal(n, 19)
t.end()
* `headers` - http headers, defaults to {}
* `body` - entity body for POST and PUT requests. Must be buffer or string.
* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.
-* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.
+* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.
* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.
* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.
+++ /dev/null
-var crypto = require('crypto')
-
-// The Authentication Header
-//
-// The Amazon S3 REST API uses the standard HTTPAuthorization header to pass authentication information. (The name of the standard header is unfortunate because it carries authentication information, not authorization).Under the Amazon S3 authentication scheme, the Authorization header has the following form.
-//
-// Authorization: AWS AWSAccessKeyId:Signature
-//
-// Developers are issued an AWS Access Key ID and AWS SecretAccess Key when they register. For request authentication, theAWSAccessKeyId element identifies the secret key that was used to compute the signature, and (indirectly) the developer making the request.
-//
-// The Signature element is the RFC 2104HMAC-SHA1 of selected elements from the request, and so theSignature part of the Authorization header will vary from request to request. If the request signature calculated by the system matches theSignature included with the request, then the requester will have demonstrated possession to the AWSSecret Access Key. The request will then be processed under the identity, and with the authority, of the developer to whom the key was issued.
-//
-// Following is pseudo-grammar that illustrates the construction of the Authorization request header (\nmeans the Unicode code point U+000A commonly called newline).
-
-function authorizationHeader (accessKey) {
- // Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;
-
- var authorization = 'AWS' + " " + accessKey + ":" + signature()
-
- return authorization
-}
-
-//
-
-function signature (secret, verb, md5, contenttype, date, amzheaders, bucket, path) {
- // Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) );
-
- function encodeSignature (stringToSign) {
- return crypto.createHash('sha1').update(stringToSign).digest('base64')
- }
-
- //
- // StringToSign = HTTP-Verb + "\n" +
- // Content-MD5 + "\n" +
- // Content-Type + "\n" +
- // Date + "\n" +
- // CanonicalizedAmzHeaders +
- // CanonicalizedResource;
-
- function compileStringToSign () {
- var s =
- verb + '\n'
- (md5 || '') + '\n'
- (contenttype || '') + '\n'
- date.toUTCString() + '\n'
- canonicalizeAmzHeaders(amzheaders) +
- canonicalizeResource()
- return s
- }
-
- //
- // CanonicalizedResource = [ "/" + Bucket ] +
- // <HTTP-Request-URI, from the protocol name up to the query string> +
- // [ sub-resource, if present. For example "?acl", "?location", "?logging", or "?torrent"];
-
- function canonicalizeResource () {
- return '/' + bucket + path
- }
-
- //
- // CanonicalizedAmzHeaders = <described below>
- //
- // HMAC-SHA1 is an algorithm defined by RFC 2104 (go to RFC 2104 - Keyed-Hashing for Message Authentication ). The algorithm takes as input two byte-strings: a key and a message. For Amazon S3 Request authentication, use your AWS Secret Access Key (YourSecretAccessKeyID) as the key, and the UTF-8 encoding of the StringToSign as the message. The output of HMAC-SHA1 is also a byte string, called the digest. The Signature request parameter is constructed by Base64 encoding this digest.
- // Request Canonicalization for Signing
- //
- // Recall that when the system receives an authenticated request, it compares the computed request signature with the signature provided in the request in StringToSign. For that reason, you must compute the signature using the same method used by Amazon S3. We call the process of putting a request in an agreed-upon form for signing "canonicalization".
-
-}
-
-
-
-// Constructing the CanonicalizedResource Element
-//
-// CanonicalizedResource represents the Amazon S3 resource targeted by the request. Construct it for a REST request as follows:
-//
-// Launch Process
-//
-// 1
-//
-//
-// Start with the empty string ("").
-//
-// 2
-//
-//
-// If the request specifies a bucket using the HTTP Host header (virtual hosted-style), append the bucket name preceded by a "/" (e.g., "/bucketname"). For path-style requests and requests that don't address a bucket, do nothing. For more information on virtual hosted-style requests, see Virtual Hosting of Buckets.
-//
-// 3
-//
-//
-// Append the path part of the un-decoded HTTP Request-URI, up-to but not including the query string.
-//
-// 4
-//
-//
-// If the request addresses a sub-resource, like ?versioning, ?location, ?acl, ?torrent, ?lifecycle, or ?versionid append the sub-resource, its value if it has one, and the question mark. Note that in case of multiple sub-resources, sub-resources must be lexicographically sorted by sub-resource name and separated by '&'. e.g. ?acl&versionId=value.
-//
-// The list of sub-resources that must be included when constructing the CanonicalizedResource Element are: acl, lifecycle, location, logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions and website.
-//
-// If the request specifies query string parameters overriding the response header values (see Get Object), append the query string parameters, and its values. When signing you do not encode these values. However, when making the request, you must encode these parameter values. The query string parameters in a GET request include response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, response-content-encoding.
-//
-// The delete query string parameter must be including when creating the CanonicalizedResource for a Multi-Object Delete request.
-//
-// Elements of the CanonicalizedResource that come from the HTTP Request-URI should be signed literally as they appear in the HTTP request, including URL-Encoding meta characters.
-//
-// The CanonicalizedResource might be different than the HTTP Request-URI. In particular, if your request uses the HTTP Host header to specify a bucket, the bucket does appear in the HTTP Request-URI. However, the CanonicalizedResource continues to include the bucket. Query string parameters might also appear in the Request-URI but are not included in CanonicalizedResource. For more information, see Virtual Hosting of Buckets.
-// Constructing the CanonicalizedAmzHeaders Element
-//
-// To construct the CanonicalizedAmzHeaders part of StringToSign, select all HTTP request headers that start with 'x-amz-' (using a case-insensitive comparison) and use the following process.
-//
-// CanonicalizedAmzHeaders Process
-// 1 Convert each HTTP header name to lower-case. For example, 'X-Amz-Date' becomes 'x-amz-date'.
-// 2 Sort the collection of headers lexicographically by header name.
-// 3 Combine header fields with the same name into one "header-name:comma-separated-value-list" pair as prescribed by RFC 2616, section 4.2, without any white-space between values. For example, the two metadata headers 'x-amz-meta-username: fred' and 'x-amz-meta-username: barney' would be combined into the single header 'x-amz-meta-username: fred,barney'.
-// 4 "Unfold" long headers that span multiple lines (as allowed by RFC 2616, section 4.2) by replacing the folding white-space (including new-line) by a single space.
-// 5 Trim any white-space around the colon in the header. For example, the header 'x-amz-meta-username: fred,barney' would become 'x-amz-meta-username:fred,barney'
-// 6 Finally, append a new-line (U+000A) to each canonicalized header in the resulting list. Construct the CanonicalizedResource element by concatenating all headers in this list into a single string.
-//
-// Positional versus Named HTTP Header StringToSign Elements
-//
-// The first few header elements of StringToSign (Content-Type, Date, and Content-MD5) are positional in nature. StringToSign does not include the names of these headers, only their values from the request. In contrast, the 'x-amz-' elements are named; Both the header names and the header values appear in StringToSign.
-//
-// If a positional header called for in the definition of StringToSign is not present in your request, (Content-Type or Content-MD5, for example, are optional for PUT requests, and meaningless for GET requests), substitute the empty string ("") in for that position.
-// Time Stamp Requirement
-//
-// A valid time stamp (using either the HTTP Date header or an x-amz-date alternative) is mandatory for authenticated requests. Furthermore, the client time-stamp included with an authenticated request must be within 15 minutes of the Amazon S3 system time when the request is received. If not, the request will fail with the RequestTimeTooSkewed error status code. The intention of these restrictions is to limit the possibility that intercepted requests could be replayed by an adversary. For stronger protection against eavesdropping, use the HTTPS transport for authenticated requests.
-//
-// Some HTTP client libraries do not expose the ability to set the Date header for a request. If you have trouble including the value of the 'Date' header in the canonicalized headers, you can set the time-stamp for the request using an 'x-amz-date' header instead. The value of the x-amz-date header must be in one of the RFC 2616 formats (http://www.ietf.org/rfc/rfc2616.txt). When an x-amz-date header is present in a request, the system will ignore any Date header when computing the request signature. Therefore, if you include the x-amz-date header, use the empty string for the Date when constructing the StringToSign. See the next section for an example.
var self = this
if (!options) options = {}
-
+ if (process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)) console.error('REQUEST', options)
if (!self.pool && self.pool !== false) self.pool = globalPool
self.dests = []
self.__isRequestRequest = true
// do the HTTP CONNECT dance using koichik/node-tunnel
if (http.globalAgent && self.uri.protocol === "https:") {
- self.tunnel = true
var tunnelFn = self.proxy.protocol === "http:"
? tunnel.httpsOverHttp : tunnel.httpsOverHttps
var tunnelOptions = { proxy: { host: self.proxy.hostname
- , port: +self.proxy.port
+ , port: +self.proxy.port
, proxyAuth: self.proxy.auth }
, ca: this.ca }
self.emit('error', error)
}
+ self._parserErrorHandler = function (error) {
+ if (this.res) {
+ if (this.res.request) {
+ this.res.request.emit('error', error)
+ } else {
+ this.res.emit('error', error)
+ }
+ } else {
+ this._httpMessage.emit('error', error)
+ }
+ }
+
if (options.form) {
self.form(options.form)
}
}
self.once('pipe', function (src) {
- if (self.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.")
+ if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.")
self.src = src
if (isReadStream(src)) {
if (!self.headers['content-type'] && !self.headers['Content-Type'])
})
}
+// Must call this when following a redirect from https to http or vice versa
+// Attempts to keep everything as identical as possible, but update the
+// httpModule, Tunneling agent, and/or Forever Agent in use.
+Request.prototype._updateProtocol = function () {
+ var self = this
+ var protocol = self.uri.protocol
+
+ if (protocol === 'https:') {
+ // previously was doing http, now doing https
+ // if it's https, then we might need to tunnel now.
+ if (self.proxy) {
+ self.tunnel = true
+ var tunnelFn = self.proxy.protocol === 'http:'
+ ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
+ var tunnelOptions = { proxy: { host: self.proxy.hostname
+ , post: +self.proxy.port
+ , proxyAuth: self.proxy.auth }
+ , ca: self.ca }
+ self.agent = tunnelFn(tunnelOptions)
+ return
+ }
+
+ self.httpModule = https
+ switch (self.agentClass) {
+ case ForeverAgent:
+ self.agentClass = ForeverAgent.SSL
+ break
+ case http.Agent:
+ self.agentClass = https.Agent
+ break
+ default:
+ // nothing we can do. Just hope for the best.
+ return
+ }
+
+ // if there's an agent, we need to get a new one.
+ if (self.agent) self.agent = self.getAgent()
+
+ } else {
+ if (log) log('previously https, now http')
+ // previously was doing https, now doing http
+ // stop any tunneling.
+ if (self.tunnel) self.tunnel = false
+ self.httpModule = http
+ switch (self.agentClass) {
+ case ForeverAgent.SSL:
+ self.agentClass = ForeverAgent
+ break
+ case https.Agent:
+ self.agentClass = http.Agent
+ break
+ default:
+ // nothing we can do. just hope for the best
+ return
+ }
+
+ // if there's an agent, then get a new one.
+ if (self.agent) {
+ self.agent = null
+ self.agent = self.getAgent()
+ }
+ }
+}
+
Request.prototype.getAgent = function () {
var Agent = this.agentClass
var options = {}
poolKey += this.host + ':' + this.port
}
- if (options.ca) {
+ // ca option is only relevant if proxy or destination are https
+ var proxy = this.proxy
+ if (typeof proxy === 'string') proxy = url.parse(proxy)
+ var caRelevant = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:'
+ if (options.ca && caRelevant) {
if (poolKey) poolKey += ':'
poolKey += options.ca
}
return this.httpModule.globalAgent
}
+ // we're using a stored agent. Make sure it's protocol-specific
+ poolKey = this.uri.protocol + poolKey
+
// already generated an agent for this setting
if (this.pool[poolKey]) return this.pool[poolKey]
Request.prototype.start = function () {
var self = this
-
+
if (self._aborted) return
-
+
self._started = true
self.method = self.method || 'GET'
self.href = self.uri.href
if (log) log('%method %href', self)
-
+
if (self.src && self.src.stat && self.src.stat.size) {
self.headers['content-length'] = self.src.stat.size
}
if (self._aws) {
self.aws(self._aws, true)
}
-
+
self.req = self.httpModule.request(self, function (response) {
+ if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) {
+ response.connection.once('error', self._parserErrorHandler)
+ }
if (self._aborted) return
if (self._paused) response.pause()
-
+
self.response = response
response.request = self
response.toJSON = toJSON
clearTimeout(self.timeoutTimer)
self.timeoutTimer = null
}
-
+
var addCookie = function (cookie) {
if (self._jar) self._jar.add(new Cookie(cookie))
else cookieJar.add(new Cookie(cookie))
if (!isUrl.test(response.headers.location)) {
response.headers.location = url.resolve(self.uri.href, response.headers.location)
}
- self.uri = response.headers.location
+
+ var uriPrev = self.uri
+ self.uri = url.parse(response.headers.location)
+
+ // handle the case where we change protocol from https to http or vice versa
+ if (self.uri.protocol !== uriPrev.protocol) {
+ self._updateProtocol()
+ }
+
self.redirects.push(
{ statusCode : response.statusCode
, redirectUri: response.headers.location
if (self.encoding === null) {
response.body = body
} else {
- response.body = body.toString()
+ response.body = body.toString(self.encoding)
}
} else if (buffer.length) {
response.body = buffer.join('')
self.req.on('drain', function() {
self.emit('drain')
})
-
+ self.on('end', function() {
+ self.req.connection.removeListener('error', self._parserErrorHandler)
+ })
self.emit('request', self.req)
}
self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary;
}
- console.log('boundary >> ' + self.boundary)
-
if (!multipart.forEach) throw new Error('Argument error, options.multipart.')
+ if (self.preambleCRLF) {
+ self.body.push(new Buffer('\r\n'))
+ }
+
multipart.forEach(function (part) {
var body = part.body
if(body == null) throw Error('Body attribute missing in multipart.')
// skip
} else {
delete oa['oauth_'+i]
+ delete oa[i]
}
}
this.headers.Authorization =
module.exports = request
-request.defaults = function (options) {
+request.initParams = initParams;
+
+request.defaults = function (options, requester) {
var def = function (method) {
var d = function (uri, opts, callback) {
var params = initParams(uri, opts, callback);
for (var i in options) {
if (params.options[i] === undefined) params.options[i] = options[i]
}
- return method(params.options, params.callback)
+ if(typeof requester === 'function') {
+ if(method === request) {
+ method = requester;
+ } else {
+ params.options._requester = requester;
+ }
+ }
+ return method(params.options, params.callback);
}
- return d
+ return d;
}
var de = def(request)
de.get = def(request.get)
request.del = function (uri, options, callback) {
var params = initParams(uri, options, callback);
params.options.method = 'DELETE'
+ if(typeof params.options._requester === 'function') {
+ request = params.options._requester;
+ }
return request(params.uri || null, params.options, params.callback)
}
request.jar = function () {
"scripts": {
"test": "node tests/run.js"
},
- "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n<pre>\n npm install request\n</pre>\n\nOr from source:\n\n<pre>\n git clone git://github.com/mikeal/request.git \n cd request\n npm link\n</pre>\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n",
+ "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n<pre>\n npm install request\n</pre>\n\nOr from source:\n\n<pre>\n git clone git://github.com/mikeal/request.git \n cd request\n npm link\n</pre>\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n",
"_id": "request@2.9.203",
"dist": {
- "shasum": "f4c8f35b61b4d6621cb287bb1a1be6002b0bbe4a"
+ "shasum": "baf55a9b2ccfcca405cfcc0b104edf8b2681eeef"
},
- "_from": "request@~2.9"
+ "_from": "git://github.com/isaacs/request"
}
var r = '';
req.on('data', function (chunk) {r += chunk})
req.on('end', function () {
- if (r !== text) console.log(r, text);
- assert.equal(r, text)
- resp.writeHead(200, {'content-type':'text/plain'})
- resp.write('OK')
- resp.end()
+ if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) {
+ var boundary = req.headers['content-type'].split('boundary=')[1];
+ text = text.replace(/__BOUNDARY__/g, boundary);
+ }
+ if (r !== text) console.log(r, text);
+ assert.equal(r, text)
+ resp.writeHead(200, {'content-type':'text/plain'})
+ resp.write('OK')
+ resp.end()
})
}
return l;
, encoding: null
, expectBody: new Buffer("TESTING!")
}
+ , testGetEncoding :
+ { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex'))
+ , encoding: 'hex'
+ , expectBody: "efa3bfcea9e29883"
+ }
, testGetJSON :
{ resp : server.createGetResponse('{"test":true}', 'application/json')
, json : true
, method: "PUT"
, json: {foo: 'bar'}
}
-
+ , testPutMultipart :
+ { resp: server.createPostValidator(
+ '--__BOUNDARY__\r\n' +
+ 'content-type: text/html\r\n' +
+ '\r\n' +
+ '<html><body>Oh hi.</body></html>' +
+ '\r\n--__BOUNDARY__\r\n\r\n' +
+ 'Oh hi.' +
+ '\r\n--__BOUNDARY__--'
+ )
+ , method: "PUT"
+ , multipart:
+ [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+ , {'body': 'Oh hi.'}
+ ]
+ }
+ , testPutMultipartPreambleCRLF :
+ { resp: server.createPostValidator(
+ '\r\n--__BOUNDARY__\r\n' +
+ 'content-type: text/html\r\n' +
+ '\r\n' +
+ '<html><body>Oh hi.</body></html>' +
+ '\r\n--__BOUNDARY__\r\n\r\n' +
+ 'Oh hi.' +
+ '\r\n--__BOUNDARY__--'
+ )
+ , method: "PUT"
+ , preambleCRLF: true
+ , multipart:
+ [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+ , {'body': 'Oh hi.'}
+ ]
+ }
}
s.listen(s.port, function () {
request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){
if (e) throw e;
counter += 1;
- console.log(counter.toString() + " tests passed.")
- s.close()
});
+ s.on('/get_custom', function(req, resp) {
+ assert.equal(req.headers.foo, 'bar');
+ assert.equal(req.headers.x, 'y');
+ resp.writeHead(200, {'Content-Type': 'text/plain'});
+ resp.end();
+ });
+
+ // test custom request handler function
+ var defaultRequest = request.defaults({
+ headers:{foo:"bar"}
+ , body: 'TESTING!'
+ }, function(uri, options, callback) {
+ var params = request.initParams(uri, options, callback);
+ options = params.options;
+ options.headers.x = 'y';
+
+ return request(params.uri, params.options, params.callback);
+ });
+
+ var msg = 'defaults test failed. head request should throw earlier';
+ assert.throws(function() {
+ defaultRequest.head(s.url + '/get_custom', function(e, r, b) {
+ throw new Error(msg);
+ });
+ counter+=1;
+ }, msg);
+
+ defaultRequest.get(s.url + '/get_custom', function(e, r, b) {
+ if(e) throw e;
+ counter += 1;
+ console.log(counter.toString() + " tests passed.");
+ s.close();
+ });
})
--- /dev/null
+var request = require('request');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+ console.error(req.method, req.url);
+ requests ++;
+
+ if (req.method === 'POST') {
+ console.error('send 303');
+ res.setHeader('location', req.url);
+ res.statusCode = 303;
+ res.end('try again, i guess\n');
+ } else {
+ console.error('send 200')
+ res.end('ok: ' + requests);
+ }
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+ followAllRedirects: true,
+ form: { foo: 'bar' } }, function (er, req, body) {
+ if (er) throw er;
+ assert.equal(body, 'ok: 2');
+ assert.equal(requests, 2);
+ console.error('ok - ' + process.version);
+ server.close();
+});
--- /dev/null
+var request = require('request');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+ requests ++;
+
+ // redirect everything 3 times, no matter what.
+ var c = req.headers.cookie;
+
+ if (!c) c = 0;
+ else c = +c.split('=')[1] || 0;
+
+ if (c > 3) {
+ res.end('ok: '+requests);
+ return;
+ }
+
+ res.setHeader('set-cookie', 'c=' + (c + 1));
+ res.setHeader('location', req.url);
+ res.statusCode = 302;
+ res.end('try again, i guess\n');
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+ followAllRedirects: true,
+ form: { foo: 'bar' } }, function (er, req, body) {
+ if (er) throw er;
+ assert.equal(body, 'ok: 5');
+ assert.equal(requests, 5);
+ console.error('ok - ' + process.version);
+ server.close();
+});
}
, testPutMultipart :
{ resp: server.createPostValidator(
- '--frontier\r\n' +
+ '--__BOUNDARY__\r\n' +
'content-type: text/html\r\n' +
'\r\n' +
'<html><body>Oh hi.</body></html>' +
- '\r\n--frontier\r\n\r\n' +
+ '\r\n--__BOUNDARY__\r\n\r\n' +
'Oh hi.' +
- '\r\n--frontier--'
+ '\r\n--__BOUNDARY__--'
)
, method: "PUT"
, multipart:
}
, testPutMultipart :
{ resp: server.createPostValidator(
- '--frontier\r\n' +
+ '--__BOUNDARY__\r\n' +
'content-type: text/html\r\n' +
'\r\n' +
'<html><body>Oh hi.</body></html>' +
- '\r\n--frontier\r\n\r\n' +
+ '\r\n--__BOUNDARY__\r\n\r\n' +
'Oh hi.' +
- '\r\n--frontier--'
+ '\r\n--__BOUNDARY__--'
)
, method: "PUT"
, multipart:
}
, testPutMultipart :
{ resp: server.createPostValidator(
- '--frontier\r\n' +
+ '--__BOUNDARY__\r\n' +
'content-type: text/html\r\n' +
'\r\n' +
'<html><body>Oh hi.</body></html>' +
- '\r\n--frontier\r\n\r\n' +
+ '\r\n--__BOUNDARY__\r\n\r\n' +
'Oh hi.' +
- '\r\n--frontier--'
+ '\r\n--__BOUNDARY__--'
)
, method: "PUT"
, multipart:
--- /dev/null
+var server = require('./server')
+ , assert = require('assert')
+ , request = require('../main.js')
+
+
+var s = server.createServer()
+var ss = server.createSSLServer()
+var sUrl = 'http://localhost:' + s.port
+var ssUrl = 'https://localhost:' + ss.port
+
+s.listen(s.port, bouncy(s, ssUrl))
+ss.listen(ss.port, bouncy(ss, sUrl))
+
+var hits = {}
+var expect = {}
+var pending = 0
+function bouncy (s, server) { return function () {
+
+ var redirs = { a: 'b'
+ , b: 'c'
+ , c: 'd'
+ , d: 'e'
+ , e: 'f'
+ , f: 'g'
+ , g: 'h'
+ , h: 'end' }
+
+ var perm = true
+ Object.keys(redirs).forEach(function (p) {
+ var t = redirs[p]
+
+ // switch type each time
+ var type = perm ? 301 : 302
+ perm = !perm
+ s.on('/' + p, function (req, res) {
+ res.writeHead(type, { location: server + '/' + t })
+ res.end()
+ })
+ })
+
+ s.on('/end', function (req, res) {
+ var h = req.headers['x-test-key']
+ hits[h] = true
+ pending --
+ if (pending === 0) done()
+ })
+}}
+
+for (var i = 0; i < 5; i ++) {
+ pending ++
+ var val = 'test_' + i
+ expect[val] = true
+ request({ url: (i % 2 ? sUrl : ssUrl) + '/a'
+ , headers: { 'x-test-key': val } })
+}
+
+function done () {
+ assert.deepEqual(hits, expect)
+ process.exit(0)
+}
+++ /dev/null
-var request = require('../main')
-
-var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/',
- { aws:
- { key: 'AKIAI6KIQRRVMGK3WK5Q'
- , secret: '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'
- , bucket: 'log.curlybracecast.com'
- }
- }, function (e, resp, body) {
- console.log(r.headers)
- console.log(body)
- }
-)
\ No newline at end of file
})
squid.on('exit', function (c) {
- console.error('exit '+c)
+ console.error('squid: exit '+c)
if (c && !ready) {
console.error('squid must be installed to run this test.')
+ console.error('skipping this test. please install squid and run again if you need to test tunneling.')
c = null
hadError = null
process.exit(0)
setTimeout(function F () {
if (!ready) return setTimeout(F, 100)
- request({ uri: 'https://registry.npmjs.org/request/'
+ request({ uri: 'https://registry.npmjs.org/'
, proxy: 'http://localhost:3128'
+ , strictSSL: true
, ca: ca
, json: true }, function (er, body) {
hadError = er
TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
// 0 is dummy port for v0.6
var secureSocket = tls.connect(0, mergeOptions({}, self.options, {
+ servername: options.host,
socket: socket
}));
cb(secureSocket);
{
- "version": "1.1.49",
+ "version": "1.1.55",
"name": "npm",
"publishConfig": {
"proprietary-attribs": false
"graceful-fs": "~1.1.1",
"minimatch": "~0.2.6",
"nopt": "~2.0",
- "node-uuid": "~1.3",
"rimraf": "2",
"request": "~2.9",
"which": "1",
"block-stream": "*",
"inherits": "1",
"mkdirp": "~0.3.3",
- "read": "~1.0.3",
+ "read": "~1.0.4",
"lru-cache": "~2.0.0",
"node-gyp": "~0.6.4",
"fstream-npm": "0.1",
"chownr": "0",
"npmlog": "0",
"ansi": "~0.1.2",
- "npm-registry-client": "~0.1.4",
+ "npm-registry-client": "~0.2.4",
"read-package-json": "~0.1.3",
"read-installed": "0",
"glob": "~3.1.12",
"graceful-fs",
"minimatch",
"nopt",
- "node-uuid",
"rimraf",
"request",
"which",
"tap": "~0.2.5"
},
"engines": {
- "node": ">=0.8",
+ "node": ">=0.6",
"npm": "1"
},
"scripts": {
--- /dev/null
+var test = require('tap').test
+var fs = require('fs')
+var pkg = process.env.npm_config_tmp || '/tmp'
+pkg += '/npm-test-publish-config'
+
+require('mkdirp').sync(pkg)
+
+fs.writeFileSync(pkg + '/package.json', JSON.stringify({
+ name: 'npm-test-publish-config',
+ version: '1.2.3',
+ publishConfig: { registry: 'http://localhost:13370' }
+}), 'utf8')
+
+var spawn = require('child_process').spawn
+var npm = require.resolve('../../bin/npm-cli.js')
+var node = process.execPath
+
+console.error('pkg=%j', pkg)
+
+test(function (t) {
+ var child
+ require('http').createServer(function (req, res) {
+ t.pass('got request on the fakey fake registry')
+ t.end()
+ this.close()
+ res.statusCode = 500
+ res.end('{"error":"sshhh. naptime nao. \\^O^/ <(YAWWWWN!)"}')
+ child.kill()
+ }).listen(13370, function () {
+ t.pass('server is listening')
+
+ // don't much care about listening to the child's results
+ // just wanna make sure it hits the server we just set up.
+ //
+ // there are plenty of other tests to verify that publish
+ // itself functions normally.
+ child = spawn(node, [npm, 'publish'], {
+ cwd: pkg
+ })
+ })
+})