+### v2.4.1 (2015-01-23):
+
+
+
+Let's accentuate the positive: the `dist-tag` endpoints for `npm dist-tag
+{add,rm,ls}` are now live on the public npm registry.
+
+* [`f70272b`](https://github.com/npm/npm/commit/f70272bed7d77032d1e21553371dd5662fef32f2)
+ `npm-registry-client@6.0.3`: Properly escape JSON tag version strings and
+ filter `_etag` from CouchDB docs. ([@othiym23](https://github.com/othiym23))
+
+### v2.4.0 (2015-01-22):
+
+#### REGISTRY 2: ACCESS AND DIST-TAGS
+
+NOTE: This week's registry-2 commands are leading the implementation on
+registry.npmjs.org a little bit, so some of the following may not work for
+another week or so. Also note that `npm access` has documentation and
+subcommands that are not yet finished, because they depend on incompletely
+specified registry API endpoints. Things are coming together very quickly,
+though, so expect the missing pieces to be filled in the coming weeks.
+
+* [`c963eb2`](https://github.com/npm/npm/commit/c963eb295cf766921b1680f4a71fd0ed3e1bcad8)
+ [#7181](https://github.com/npm/npm/issues/7181) NEW `npm access public` and
+ `npm access restricted`: Toggle visibility of scoped packages.
+ ([@othiym23](https://github.com/othiym23))
+* [`dc51810`](https://github.com/npm/npm/commit/dc51810e08c0f104259146c9c035d255de4f7d1d)
+ [#6243](https://github.com/npm/npm/issues/6243) /
+ [#6854](https://github.com/npm/npm/issues/6854) NEW `npm dist-tags`: Directly
+ manage `dist-tags` on packages. Most notably, `dist-tags` can now be deleted.
+ ([@othiym23](https://github.com/othiym23))
+* [`4c7c132`](https://github.com/npm/npm/commit/4c7c132a6b8305dca2974943226c39c0cdc64ff9)
+ [#7181](https://github.com/npm/npm/issues/7181) /
+ [#6854](https://github.com/npm/npm/issues/6854) `npm-registry-client@6.0.1`:
+ Add new `access` and `dist-tags` endpoints
+ ([@othiym23](https://github.com/othiym23))
+
+#### NOT EXACTLY SELF-DEPRECATING
+
+* [`10d5c77`](https://github.com/npm/npm/commit/10d5c77653487f15759ac7de262a97e9c655240c)
+ [#6274](https://github.com/npm/npm/issues/6274) Deprecate `npm tag` in favor
+ of `npm dist-tag`. ([@othiym23](https://github.com/othiym23))
+
+#### BUG FIX AND TINY FEATURE
+
+* [`29a6ef3`](https://github.com/npm/npm/commit/29a6ef38ef86ac318c5d9ea4bee28ce614672fa6)
+ [#6850](https://github.com/npm/npm/issues/6850) Be smarter about determining
+ base of file deletion when unbuilding. ([@phated](https://github.com/phated))
+* [`4ad01ea`](https://github.com/npm/npm/commit/4ad01ea2930a7a1cf88be121cc5ce9eba40c6807)
+ `init-package-json@1.2.0`: Support `--save-exact` in `npm init`.
+ ([@gustavnikolaj](https://github.com/gustavnikolaj))
+
### v2.3.0 (2015-01-15):
#### REGISTRY 2: OH MY STARS! WHO AM I?
--- /dev/null
+npm-access(1) -- Set access level on published packages
+=======================================================
+
+## SYNOPSIS
+
+ npm access public [<package>]
+ npm access restricted [<package>]
+
+ npm access add <read-only|read-write> <entity> [<package>]
+ npm access rm <entity> [<package>]
+
+ npm access ls [<package>]
+ npm access edit [<package>]
+
+## DESCRIPTION
+
+Used to set access controls on private packages.
+
+For all of the subcommands, `npm access` will perform actions on the packages
+in the current working directory if no package name is passed to the
+subcommand.
+
+* public / restricted:
+ Set a package to be either publicly accessible or restricted.
+
+* add / rm:
+ Add or remove the ability of users and teams to have read-only or read-write
+ access to a package.
+
+* ls:
+ Show all of the access privileges for a package. Will only show permissions
+ for packages to which you have at least read access.
+
+* edit:
+ Set the access privileges for a package at once using `$EDITOR`.
+
+## DETAILS
+
+`npm access` always operates directly on the current registry, configurable
+from the command line using `--registry=<registry url>`.
+
+Unscoped packages are *always public*.
+
+Scoped packages *default to restricted*, but you can either publish them as
+public using `npm publish --access=public`, or set their access as public using
+`npm access public` after the initial publish.
+
+You must have privileges to set the access of a package:
+
+* You are an owner of an unscoped or scoped package.
+* You are a member of the team that owns a scope.
+* You have been given read-write privileges for a package, either as a member
+ of a team or directly as an owner.
+
+If your account is not paid, then attempts to publish scoped packages will fail
+with an HTTP 402 status code (logically enough), unless you use
+`--access=public`.
+
+## SEE ALSO
+
+* npm-publish(1)
+* npm-config(7)
+* npm-registry(7)
--- /dev/null
+npm-dist-tag(1) -- Modify package distribution tags
+===================================================
+
+## SYNOPSIS
+
+ npm dist-tag add <pkg>@<version> [<tag>]
+ npm dist-tag rm <pkg> <tag>
+ npm dist-tag ls [<pkg>]
+
+## DESCRIPTION
+
+Add, remove, and enumerate distribution tags on a package:
+
+* add:
+ Tags the specified version of the package with the specified tag, or the
+ `--tag` config if not specified.
+
+* rm:
+ Clear a tag that is no longer in use from the package.
+
+* ls:
+ Show all of the dist-tags for a package, defaulting to the package in
+ the curren prefix.
+
+A tag can be used when installing packages as a reference to a version instead
+of using a specific version number:
+
+ npm install <name>@<tag>
+
+When installing dependencies, a preferred tagged version may be specified:
+
+ npm install --tag <tag>
+
+This also applies to `npm dedupe`.
+
+Publishing a package always sets the "latest" tag to the published version.
+
+## PURPOSE
+
+Tags can be used to provide an alias instead of version numbers. For
+example, `npm` currently uses the tag "next" to identify the upcoming
+version, and the tag "latest" to identify the current version.
+
+A project might choose to have multiple streams of development, e.g.,
+"stable", "canary".
+
+## CAVEATS
+
+This command used to be known as `npm tag`, which only created new tags, and so
+had a different syntax.
+
+Tags must share a namespace with version numbers, because they are specified in
+the same slot: `npm install <pkg>@<version>` vs `npm install <pkg>@<tag>`.
+
+Tags that can be interpreted as valid semver ranges will be rejected. For
+example, `v1.4` cannot be used as a tag, because it is interpreted by semver as
+`>=1.4.0 <1.5.0`. See <https://github.com/npm/npm/issues/6082>.
+
+The simplest way to avoid semver problems with tags is to use tags that do not
+begin with a number or the letter `v`.
+
+## SEE ALSO
+
+* npm-tag(1)
+* npm-publish(1)
+* npm-install(1)
+* npm-dedupe(1)
+* npm-registry(7)
+* npm-config(1)
+* npm-config(7)
+* npm-tag(3)
+* npmrc(5)
## SYNOPSIS
- npm publish <tarball> [--tag <tag>]
- npm publish <folder> [--tag <tag>]
+ npm publish <tarball> [--tag <tag>] [--access <public|restricted>]
+ npm publish <folder> [--tag <tag>] [--access <public|restricted>]
## DESCRIPTION
<name>@<tag>` will install this version. By default, `npm publish` updates
and `npm install` installs the `latest` tag.
+* `[--access <public|restricted>]`
+ Tells the registry whether this package should be published as public or
+ restricted. Only applies to scoped packages, which default to `restricted`.
+ If you don't have a paid account, you must publish with `--access public`
+ to publish scoped packages.
+
Fails if the package name and version combination already exists in
the specified registry.
## SEE ALSO
* npm-registry(7)
+* npm-scope(7)
* npm-adduser(1)
* npm-owner(1)
* npm-deprecate(1)
## DESCRIPTION
+THIS COMMAND IS DEPRECATED. See npm-dist-tag(1) for details.
+
Tags the specified version of the package with the specified tag, or the
`--tag` config if not specified.
## Config Settings
+### access
+
+* Default: `restricted`
+* Type: Access
+
+When publishing scoped packages, the access level defaults to `restricted`. If
+you want your scoped package to be publicly viewable (and installable) set
+`--access=public`. The only valid values for `access` are `public` and
+`restricted`. Unscoped packages _always_ have an access level of `public`.
+
### always-auth
* Default: false
javascript package manager
+### npm-access(1)
+
+Set access level on published packages
+
### npm-adduser(1)
Add a registry user account
Deprecate a version of a package
+### npm-dist-tag(1)
+
+Modify package distribution tags
+
### npm-docs(1)
Docs for a package in a web browser maybe
<p>If you have a complaint about a package in the public npm registry,
and cannot <a href="https://docs.npmjs.com/misc/disputes">resolve it with the package
owner</a>, please email
-<a href="mailto:support@npmjs.com">support@npmjs.com</a> and explain the situation.</p>
+<a href="mailto:support@npmjs.com">support@npmjs.com</a> and explain the situation.</p>
<p>Any data published to The npm Registry (including user account
information) may be removed or modified at the sole discretion of the
npm server administrators.</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer"><a href="../doc/README.html">README</a> — npm@2.3.0</p>
+<p id="footer"><a href="../doc/README.html">README</a> — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-bin — npm@2.3.0</p>
+<p id="footer">npm-bin — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-bugs — npm@2.3.0</p>
+<p id="footer">npm-bugs — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-cache — npm@2.3.0</p>
+<p id="footer">npm-cache — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-commands — npm@2.3.0</p>
+<p id="footer">npm-commands — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-config — npm@2.3.0</p>
+<p id="footer">npm-config — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-deprecate — npm@2.3.0</p>
+<p id="footer">npm-deprecate — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-docs — npm@2.3.0</p>
+<p id="footer">npm-docs — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-edit — npm@2.3.0</p>
+<p id="footer">npm-edit — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-explore — npm@2.3.0</p>
+<p id="footer">npm-explore — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-help-search — npm@2.3.0</p>
+<p id="footer">npm-help-search — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-init — npm@2.3.0</p>
+<p id="footer">npm-init — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-install — npm@2.3.0</p>
+<p id="footer">npm-install — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-link — npm@2.3.0</p>
+<p id="footer">npm-link — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-load — npm@2.3.0</p>
+<p id="footer">npm-load — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-ls — npm@2.3.0</p>
+<p id="footer">npm-ls — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-outdated — npm@2.3.0</p>
+<p id="footer">npm-outdated — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-owner — npm@2.3.0</p>
+<p id="footer">npm-owner — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-pack — npm@2.3.0</p>
+<p id="footer">npm-pack — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-prefix — npm@2.3.0</p>
+<p id="footer">npm-prefix — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-prune — npm@2.3.0</p>
+<p id="footer">npm-prune — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-publish — npm@2.3.0</p>
+<p id="footer">npm-publish — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-rebuild — npm@2.3.0</p>
+<p id="footer">npm-rebuild — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-repo — npm@2.3.0</p>
+<p id="footer">npm-repo — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-restart — npm@2.3.0</p>
+<p id="footer">npm-restart — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-root — npm@2.3.0</p>
+<p id="footer">npm-root — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-run-script — npm@2.3.0</p>
+<p id="footer">npm-run-script — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-search — npm@2.3.0</p>
+<p id="footer">npm-search — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-shrinkwrap — npm@2.3.0</p>
+<p id="footer">npm-shrinkwrap — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-start — npm@2.3.0</p>
+<p id="footer">npm-start — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-stop — npm@2.3.0</p>
+<p id="footer">npm-stop — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-tag — npm@2.3.0</p>
+<p id="footer">npm-tag — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-test — npm@2.3.0</p>
+<p id="footer">npm-test — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-uninstall — npm@2.3.0</p>
+<p id="footer">npm-uninstall — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-unpublish — npm@2.3.0</p>
+<p id="footer">npm-unpublish — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-update — npm@2.3.0</p>
+<p id="footer">npm-update — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-version — npm@2.3.0</p>
+<p id="footer">npm-version — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-view — npm@2.3.0</p>
+<p id="footer">npm-view — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-whoami — npm@2.3.0</p>
+<p id="footer">npm-whoami — npm@2.4.1</p>
npm.commands.install(["package"], cb)
})
</code></pre><h2 id="version">VERSION</h2>
-<p>2.3.0</p>
+<p>2.4.1</p>
<h2 id="description">DESCRIPTION</h2>
<p>This is the API documentation for npm.
To find documentation of the command line
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm — npm@2.3.0</p>
+<p id="footer">npm — npm@2.4.1</p>
--- /dev/null
+<!doctype html>
+<html>
+ <title>npm-access</title>
+ <meta http-equiv="content-type" value="text/html;utf-8">
+ <link rel="stylesheet" type="text/css" href="../../static/style.css">
+ <link rel="canonical" href="https://www.npmjs.org/doc/cli/npm-access.html">
+ <script async=true src="../../static/toc.js"></script>
+
+ <body>
+ <div id="wrapper">
+
+<h1><a href="../cli/npm-access.html">npm-access</a></h1> <p>Set access level on published packages</p>
+<h2 id="synopsis">SYNOPSIS</h2>
+<pre><code>npm access public [<package>]
+npm access restricted [<package>]
+
+npm access add <read-only|read-write> <entity> [<package>]
+npm access rm <entity> [<package>]
+
+npm access ls [<package>]
+npm access edit [<package>]
+</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>Used to set access controls on private packages.</p>
+<p>For all of the subcommands, <code>npm access</code> will perform actions on the packages
+in the current working directory if no package name is passed to the
+subcommand.</p>
+<ul>
+<li><p>public / restricted:
+Set a package to be either publicly accessible or restricted.</p>
+</li>
+<li><p>add / rm:
+Add or remove the ability of users and teams to have read-only or read-write
+access to a package.</p>
+</li>
+<li><p>ls:
+Show all of the access privileges for a package. Will only show permissions
+for packages to which you have at least read access.</p>
+</li>
+<li><p>edit:
+Set the access privileges for a package at once using <code>$EDITOR</code>.</p>
+</li>
+</ul>
+<h2 id="details">DETAILS</h2>
+<p><code>npm access</code> always operates directly on the current registry, configurable
+from the command line using <code>--registry=<registry url></code>.</p>
+<p>Unscoped packages are <em>always public</em>.</p>
+<p>Scoped packages <em>default to restricted</em>, but you can either publish them as
+public using <code>npm publish --access=public</code>, or set their access as public using
+<code>npm access public</code> after the initial publish.</p>
+<p>You must have privileges to set the access of a package:</p>
+<ul>
+<li>You are an owner of an unscoped or scoped package.</li>
+<li>You are a member of the team that owns a scope.</li>
+<li>You have been given read-write privileges for a package, either as a member
+of a team or directly as an owner.</li>
+</ul>
+<p>If your account is not paid, then attempts to publish scoped packages will fail
+with an HTTP 402 status code (logically enough), unless you use
+<code>--access=public</code>.</p>
+<h2 id="see-also">SEE ALSO</h2>
+<ul>
+<li><a href="../cli/npm-publish.html"><a href="../cli/npm-publish.html">npm-publish(1)</a></a></li>
+<li><a href="../misc/npm-config.html"><a href="../misc/npm-config.html">npm-config(7)</a></a></li>
+<li><a href="../misc/npm-registry.html"><a href="../misc/npm-registry.html">npm-registry(7)</a></a></li>
+</ul>
+
+</div>
+
+<table border=0 cellspacing=0 cellpadding=0 id=npmlogo>
+<tr><td style="width:180px;height:10px;background:rgb(237,127,127)" colspan=18> </td></tr>
+<tr><td rowspan=4 style="width:10px;height:10px;background:rgb(237,127,127)"> </td><td style="width:40px;height:10px;background:#fff" colspan=4> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=4> </td><td style="width:40px;height:10px;background:#fff" colspan=4> </td><td rowspan=4 style="width:10px;height:10px;background:rgb(237,127,127)"> </td><td colspan=6 style="width:60px;height:10px;background:#fff"> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=4> </td></tr>
+<tr><td colspan=2 style="width:20px;height:30px;background:#fff" rowspan=3> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:20px;height:10px;background:#fff" rowspan=4 colspan=2> </td><td style="width:10px;height:20px;background:rgb(237,127,127)" rowspan=2> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:20px;height:10px;background:#fff" rowspan=3 colspan=2> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td></tr>
+<tr><td style="width:10px;height:10px;background:#fff" rowspan=2> </td></tr>
+<tr><td style="width:10px;height:10px;background:#fff"> </td></tr>
+<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
+<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
+</table>
+<p id="footer">npm-access — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-adduser — npm@2.3.0</p>
+<p id="footer">npm-adduser — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-bin — npm@2.3.0</p>
+<p id="footer">npm-bin — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-bugs — npm@2.3.0</p>
+<p id="footer">npm-bugs — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-build — npm@2.3.0</p>
+<p id="footer">npm-build — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-bundle — npm@2.3.0</p>
+<p id="footer">npm-bundle — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-cache — npm@2.3.0</p>
+<p id="footer">npm-cache — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-completion — npm@2.3.0</p>
+<p id="footer">npm-completion — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-config — npm@2.3.0</p>
+<p id="footer">npm-config — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-dedupe — npm@2.3.0</p>
+<p id="footer">npm-dedupe — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-deprecate — npm@2.3.0</p>
+<p id="footer">npm-deprecate — npm@2.4.1</p>
--- /dev/null
+<!doctype html>
+<html>
+ <title>npm-dist-tag</title>
+ <meta http-equiv="content-type" value="text/html;utf-8">
+ <link rel="stylesheet" type="text/css" href="../../static/style.css">
+ <link rel="canonical" href="https://www.npmjs.org/doc/cli/npm-dist-tag.html">
+ <script async=true src="../../static/toc.js"></script>
+
+ <body>
+ <div id="wrapper">
+
+<h1><a href="../cli/npm-dist-tag.html">npm-dist-tag</a></h1> <p>Modify package distribution tags</p>
+<h2 id="synopsis">SYNOPSIS</h2>
+<pre><code>npm dist-tag add <pkg>@<version> [<tag>]
+npm dist-tag rm <pkg> <tag>
+npm dist-tag ls [<pkg>]
+</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>Add, remove, and enumerate distribution tags on a package:</p>
+<ul>
+<li><p>add:
+Tags the specified version of the package with the specified tag, or the
+<code>--tag</code> config if not specified.</p>
+</li>
+<li><p>rm:
+Clear a tag that is no longer in use from the package.</p>
+</li>
+<li><p>ls:
+Show all of the dist-tags for a package, defaulting to the package in
+the curren prefix.</p>
+</li>
+</ul>
+<p>A tag can be used when installing packages as a reference to a version instead
+of using a specific version number:</p>
+<pre><code>npm install <name>@<tag>
+</code></pre><p>When installing dependencies, a preferred tagged version may be specified:</p>
+<pre><code>npm install --tag <tag>
+</code></pre><p>This also applies to <code>npm dedupe</code>.</p>
+<p>Publishing a package always sets the "latest" tag to the published version.</p>
+<h2 id="purpose">PURPOSE</h2>
+<p>Tags can be used to provide an alias instead of version numbers. For
+example, <code>npm</code> currently uses the tag "next" to identify the upcoming
+version, and the tag "latest" to identify the current version.</p>
+<p>A project might choose to have multiple streams of development, e.g.,
+"stable", "canary".</p>
+<h2 id="caveats">CAVEATS</h2>
+<p>This command used to be known as <code>npm tag</code>, which only created new tags, and so
+had a different syntax.</p>
+<p>Tags must share a namespace with version numbers, because they are specified in
+the same slot: <code>npm install <pkg>@<version></code> vs <code>npm install <pkg>@<tag></code>.</p>
+<p>Tags that can be interpreted as valid semver ranges will be rejected. For
+example, <code>v1.4</code> cannot be used as a tag, because it is interpreted by semver as
+<code>>=1.4.0 <1.5.0</code>. See <a href="https://github.com/npm/npm/issues/6082">https://github.com/npm/npm/issues/6082</a>.</p>
+<p>The simplest way to avoid semver problems with tags is to use tags that do not
+begin with a number or the letter <code>v</code>.</p>
+<h2 id="see-also">SEE ALSO</h2>
+<ul>
+<li><a href="../cli/npm-tag.html"><a href="../cli/npm-tag.html">npm-tag(1)</a></a></li>
+<li><a href="../cli/npm-publish.html"><a href="../cli/npm-publish.html">npm-publish(1)</a></a></li>
+<li><a href="../cli/npm-install.html"><a href="../cli/npm-install.html">npm-install(1)</a></a></li>
+<li><a href="../cli/npm-dedupe.html"><a href="../cli/npm-dedupe.html">npm-dedupe(1)</a></a></li>
+<li><a href="../misc/npm-registry.html"><a href="../misc/npm-registry.html">npm-registry(7)</a></a></li>
+<li><a href="../cli/npm-config.html"><a href="../cli/npm-config.html">npm-config(1)</a></a></li>
+<li><a href="../misc/npm-config.html"><a href="../misc/npm-config.html">npm-config(7)</a></a></li>
+<li><a href="../api/npm-tag.html"><a href="../api/npm-tag.html">npm-tag(3)</a></a></li>
+<li><a href="../files/npmrc.html"><a href="../files/npmrc.html">npmrc(5)</a></a></li>
+</ul>
+
+</div>
+
+<table border=0 cellspacing=0 cellpadding=0 id=npmlogo>
+<tr><td style="width:180px;height:10px;background:rgb(237,127,127)" colspan=18> </td></tr>
+<tr><td rowspan=4 style="width:10px;height:10px;background:rgb(237,127,127)"> </td><td style="width:40px;height:10px;background:#fff" colspan=4> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=4> </td><td style="width:40px;height:10px;background:#fff" colspan=4> </td><td rowspan=4 style="width:10px;height:10px;background:rgb(237,127,127)"> </td><td colspan=6 style="width:60px;height:10px;background:#fff"> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=4> </td></tr>
+<tr><td colspan=2 style="width:20px;height:30px;background:#fff" rowspan=3> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:20px;height:10px;background:#fff" rowspan=4 colspan=2> </td><td style="width:10px;height:20px;background:rgb(237,127,127)" rowspan=2> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:20px;height:10px;background:#fff" rowspan=3 colspan=2> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td><td style="width:10px;height:10px;background:#fff" rowspan=3> </td><td style="width:10px;height:10px;background:rgb(237,127,127)" rowspan=3> </td></tr>
+<tr><td style="width:10px;height:10px;background:#fff" rowspan=2> </td></tr>
+<tr><td style="width:10px;height:10px;background:#fff"> </td></tr>
+<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
+<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
+</table>
+<p id="footer">npm-dist-tag — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-docs — npm@2.3.0</p>
+<p id="footer">npm-docs — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-edit — npm@2.3.0</p>
+<p id="footer">npm-edit — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-explore — npm@2.3.0</p>
+<p id="footer">npm-explore — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-help-search — npm@2.3.0</p>
+<p id="footer">npm-help-search — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-help — npm@2.3.0</p>
+<p id="footer">npm-help — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-init — npm@2.3.0</p>
+<p id="footer">npm-init — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-install — npm@2.3.0</p>
+<p id="footer">npm-install — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-link — npm@2.3.0</p>
+<p id="footer">npm-link — npm@2.4.1</p>
limit the results to only the paths to the packages named. Note that
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@2.3.0 /path/to/npm
+<pre><code>npm@2.4.1 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre><p>It will print out extraneous, missing, and invalid packages.</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-ls — npm@2.3.0</p>
+<p id="footer">npm-ls — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-outdated — npm@2.3.0</p>
+<p id="footer">npm-outdated — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-owner — npm@2.3.0</p>
+<p id="footer">npm-owner — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-pack — npm@2.3.0</p>
+<p id="footer">npm-pack — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-prefix — npm@2.3.0</p>
+<p id="footer">npm-prefix — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-prune — npm@2.3.0</p>
+<p id="footer">npm-prune — npm@2.4.1</p>
<h1><a href="../cli/npm-publish.html">npm-publish</a></h1> <p>Publish a package</p>
<h2 id="synopsis">SYNOPSIS</h2>
-<pre><code>npm publish <tarball> [--tag <tag>]
-npm publish <folder> [--tag <tag>]
+<pre><code>npm publish <tarball> [--tag <tag>] [--access <public|restricted>]
+npm publish <folder> [--tag <tag>] [--access <public|restricted>]
</code></pre><h2 id="description">DESCRIPTION</h2>
<p>Publishes a package to the registry so that it can be installed by name. See
<code><a href="../misc/npm-developers.html"><a href="../misc/npm-developers.html">npm-developers(7)</a></a></code> for details on what's included in the published package, as
<name>@<tag></code> will install this version. By default, <code>npm publish</code> updates
and <code>npm install</code> installs the <code>latest</code> tag.</p>
</li>
+<li><p><code>[--access <public|restricted>]</code>
+Tells the registry whether this package should be published as public or
+restricted. Only applies to scoped packages, which default to <code>restricted</code>.
+If you don't have a paid account, you must publish with <code>--access public</code>
+to publish scoped packages.</p>
+</li>
</ul>
<p>Fails if the package name and version combination already exists in
the specified registry.</p>
<h2 id="see-also">SEE ALSO</h2>
<ul>
<li><a href="../misc/npm-registry.html"><a href="../misc/npm-registry.html">npm-registry(7)</a></a></li>
+<li><a href="../misc/npm-scope.html"><a href="../misc/npm-scope.html">npm-scope(7)</a></a></li>
<li><a href="../cli/npm-adduser.html"><a href="../cli/npm-adduser.html">npm-adduser(1)</a></a></li>
<li><a href="../cli/npm-owner.html"><a href="../cli/npm-owner.html">npm-owner(1)</a></a></li>
<li><a href="../cli/npm-deprecate.html"><a href="../cli/npm-deprecate.html">npm-deprecate(1)</a></a></li>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-publish — npm@2.3.0</p>
+<p id="footer">npm-publish — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-rebuild — npm@2.3.0</p>
+<p id="footer">npm-rebuild — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-repo — npm@2.3.0</p>
+<p id="footer">npm-repo — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-restart — npm@2.3.0</p>
+<p id="footer">npm-restart — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-rm — npm@2.3.0</p>
+<p id="footer">npm-rm — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-root — npm@2.3.0</p>
+<p id="footer">npm-root — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-run-script — npm@2.3.0</p>
+<p id="footer">npm-run-script — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-search — npm@2.3.0</p>
+<p id="footer">npm-search — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-shrinkwrap — npm@2.3.0</p>
+<p id="footer">npm-shrinkwrap — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-star — npm@2.3.0</p>
+<p id="footer">npm-star — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-stars — npm@2.3.0</p>
+<p id="footer">npm-stars — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-start — npm@2.3.0</p>
+<p id="footer">npm-start — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-stop — npm@2.3.0</p>
+<p id="footer">npm-stop — npm@2.4.1</p>
<h2 id="synopsis">SYNOPSIS</h2>
<pre><code>npm tag <name>@<version> [<tag>]
</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>THIS COMMAND IS DEPRECATED. See <a href="../cli/npm-dist-tag.html"><a href="../cli/npm-dist-tag.html">npm-dist-tag(1)</a></a> for details.</p>
<p>Tags the specified version of the package with the specified tag, or the
<code>--tag</code> config if not specified.</p>
<p>A tag can be used when installing packages as a reference to a version instead
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-tag — npm@2.3.0</p>
+<p id="footer">npm-tag — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-test — npm@2.3.0</p>
+<p id="footer">npm-test — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-uninstall — npm@2.3.0</p>
+<p id="footer">npm-uninstall — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-unpublish — npm@2.3.0</p>
+<p id="footer">npm-unpublish — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-update — npm@2.3.0</p>
+<p id="footer">npm-update — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-version — npm@2.3.0</p>
+<p id="footer">npm-version — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-view — npm@2.3.0</p>
+<p id="footer">npm-view — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-whoami — npm@2.3.0</p>
+<p id="footer">npm-whoami — npm@2.4.1</p>
<h2 id="synopsis">SYNOPSIS</h2>
<pre><code>npm <command> [args]
</code></pre><h2 id="version">VERSION</h2>
-<p>2.3.0</p>
+<p>2.4.1</p>
<h2 id="description">DESCRIPTION</h2>
<p>npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
the issues list or ask on the mailing list.</p>
<ul>
<li><a href="http://github.com/npm/npm/issues">http://github.com/npm/npm/issues</a></li>
-<li><a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
+<li><a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
</ul>
<h2 id="bugs">BUGS</h2>
<p>When you find issues, please report them:</p>
<li>web:
<a href="http://github.com/npm/npm/issues">http://github.com/npm/npm/issues</a></li>
<li>email:
-<a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
+<a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
</ul>
<p>Be sure to include <em>all</em> of the output from the npm command that didn't work
as expected. The <code>npm-debug.log</code> file is also helpful to provide.</p>
<p><a href="http://blog.izs.me/">Isaac Z. Schlueter</a> ::
<a href="https://github.com/isaacs/">isaacs</a> ::
<a href="http://twitter.com/izs">@izs</a> ::
-<a href="mailto:i@izs.me">i@izs.me</a></p>
+<a href="mailto:i@izs.me">i@izs.me</a></p>
<h2 id="see-also">SEE ALSO</h2>
<ul>
<li><a href="../cli/npm-help.html"><a href="../cli/npm-help.html">npm-help(1)</a></a></li>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm — npm@2.3.0</p>
+<p id="footer">npm — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-folders — npm@2.3.0</p>
+<p id="footer">npm-folders — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-global — npm@2.3.0</p>
+<p id="footer">npm-global — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-json — npm@2.3.0</p>
+<p id="footer">npm-json — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npmrc — npm@2.3.0</p>
+<p id="footer">npmrc — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">package.json — npm@2.3.0</p>
+<p id="footer">package.json — npm@2.4.1</p>
<p>Using npm on the command line</p>
<h3 id="npm-1-"><a href="cli/npm.html"><a href="cli/npm.html">npm(1)</a></a></h3>
<p>javascript package manager</p>
+<h3 id="npm-access-1-"><a href="cli/npm-access.html"><a href="cli/npm-access.html">npm-access(1)</a></a></h3>
+<p>Set access level on published packages</p>
<h3 id="npm-adduser-1-"><a href="cli/npm-adduser.html"><a href="cli/npm-adduser.html">npm-adduser(1)</a></a></h3>
<p>Add a registry user account</p>
<h3 id="npm-bin-1-"><a href="cli/npm-bin.html"><a href="cli/npm-bin.html">npm-bin(1)</a></a></h3>
<p>Reduce duplication</p>
<h3 id="npm-deprecate-1-"><a href="cli/npm-deprecate.html"><a href="cli/npm-deprecate.html">npm-deprecate(1)</a></a></h3>
<p>Deprecate a version of a package</p>
+<h3 id="npm-dist-tag-1-"><a href="cli/npm-dist-tag.html"><a href="cli/npm-dist-tag.html">npm-dist-tag(1)</a></a></h3>
+<p>Modify package distribution tags</p>
<h3 id="npm-docs-1-"><a href="cli/npm-docs.html"><a href="cli/npm-docs.html">npm-docs(1)</a></a></h3>
<p>Docs for a package in a web browser maybe</p>
<h3 id="npm-edit-1-"><a href="cli/npm-edit.html"><a href="cli/npm-edit.html">npm-edit(1)</a></a></h3>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">index — npm@2.3.0</p>
+<p id="footer">index — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-coding-style — npm@2.3.0</p>
+<p id="footer">npm-coding-style — npm@2.4.1</p>
<pre><code>npm config set foo:port 80
</code></pre><p>See <a href="../files/package.json.html"><a href="../files/package.json.html">package.json(5)</a></a> for more information.</p>
<h2 id="config-settings">Config Settings</h2>
+<h3 id="access">access</h3>
+<ul>
+<li>Default: <code>restricted</code></li>
+<li>Type: Access</li>
+</ul>
+<p>When publishing scoped packages, the access level defaults to <code>restricted</code>. If
+you want your scoped package to be publicly viewable (and installable) set
+<code>--access=public</code>. The only valid values for <code>access</code> are <code>public</code> and
+<code>restricted</code>. Unscoped packages <em>always</em> have an access level of <code>public</code>.</p>
<h3 id="always-auth">always-auth</h3>
<ul>
<li>Default: false</li>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-config — npm@2.3.0</p>
+<p id="footer">npm-config — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-developers — npm@2.3.0</p>
+<p id="footer">npm-developers — npm@2.4.1</p>
<h2 id="synopsis">SYNOPSIS</h2>
<ol>
<li>Get the author email with <code>npm owner ls <pkgname></code></li>
-<li>Email the author, CC <a href="mailto:support@npmjs.com">support@npmjs.com</a></li>
+<li>Email the author, CC <a href="mailto:support@npmjs.com">support@npmjs.com</a></li>
<li>After a few weeks, if there's no resolution, we'll sort it out.</li>
</ol>
<p>Don't squat on package names. Publish code or move out of the way.</p>
owner (Bob).</li>
<li>Joe emails Bob, explaining the situation <strong>as respectfully as
possible</strong>, and what he would like to do with the module name. He
-adds the npm support staff <a href="mailto:support@npmjs.com">support@npmjs.com</a> to the CC list of
+adds the npm support staff <a href="mailto:support@npmjs.com">support@npmjs.com</a> to the CC list of
the email. Mention in the email that Bob can run <code>npm owner add
joe foo</code> to add Joe as an owner of the <code>foo</code> package.</li>
<li>After a reasonable amount of time, if Bob has not responded, or if
Bob and Joe can't come to any sort of resolution, email support
-<a href="mailto:support@npmjs.com">support@npmjs.com</a> and we'll sort it out. ("Reasonable" is
+<a href="mailto:support@npmjs.com">support@npmjs.com</a> and we'll sort it out. ("Reasonable" is
usually at least 4 weeks, but extra time is allowed around common
holidays.)</li>
</ol>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-disputes — npm@2.3.0</p>
+<p id="footer">npm-disputes — npm@2.4.1</p>
<p>To check if the registry is down, open up
<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a> in a web browser. This will also tell
you if you are just unable to access the internet for some reason.</p>
-<p>If the registry IS down, let us know by emailing <a href="mailto:support@npmjs.com">support@npmjs.com</a>
+<p>If the registry IS down, let us know by emailing <a href="mailto:support@npmjs.com">support@npmjs.com</a>
or posting an issue at <a href="https://github.com/npm/npm/issues">https://github.com/npm/npm/issues</a>. If it's
down for the world (and not just on your local network) then we're
probably already being pinged about it.</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-faq — npm@2.3.0</p>
+<p id="footer">npm-faq — npm@2.4.1</p>
<p>Using npm on the command line</p>
<h3 id="npm-1-"><a href="../cli/npm.html"><a href="../cli/npm.html">npm(1)</a></a></h3>
<p>javascript package manager</p>
+<h3 id="npm-access-1-"><a href="../cli/npm-access.html"><a href="../cli/npm-access.html">npm-access(1)</a></a></h3>
+<p>Set access level on published packages</p>
<h3 id="npm-adduser-1-"><a href="../cli/npm-adduser.html"><a href="../cli/npm-adduser.html">npm-adduser(1)</a></a></h3>
<p>Add a registry user account</p>
<h3 id="npm-bin-1-"><a href="../cli/npm-bin.html"><a href="../cli/npm-bin.html">npm-bin(1)</a></a></h3>
<p>Reduce duplication</p>
<h3 id="npm-deprecate-1-"><a href="../cli/npm-deprecate.html"><a href="../cli/npm-deprecate.html">npm-deprecate(1)</a></a></h3>
<p>Deprecate a version of a package</p>
+<h3 id="npm-dist-tag-1-"><a href="../cli/npm-dist-tag.html"><a href="../cli/npm-dist-tag.html">npm-dist-tag(1)</a></a></h3>
+<p>Modify package distribution tags</p>
<h3 id="npm-docs-1-"><a href="../cli/npm-docs.html"><a href="../cli/npm-docs.html">npm-docs(1)</a></a></h3>
<p>Docs for a package in a web browser maybe</p>
<h3 id="npm-edit-1-"><a href="../cli/npm-edit.html"><a href="../cli/npm-edit.html">npm-edit(1)</a></a></h3>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-index — npm@2.3.0</p>
+<p id="footer">npm-index — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-registry — npm@2.3.0</p>
+<p id="footer">npm-registry — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-scope — npm@2.3.0</p>
+<p id="footer">npm-scope — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">npm-scripts — npm@2.3.0</p>
+<p id="footer">npm-scripts — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">removing-npm — npm@2.3.0</p>
+<p id="footer">removing-npm — npm@2.4.1</p>
<tr><td style="width:60px;height:10px;background:rgb(237,127,127)" colspan=6> </td><td colspan=10 style="width:10px;height:10px;background:rgb(237,127,127)"> </td></tr>
<tr><td colspan=5 style="width:50px;height:10px;background:#fff"> </td><td style="width:40px;height:10px;background:rgb(237,127,127)" colspan=4> </td><td style="width:90px;height:10px;background:#fff" colspan=9> </td></tr>
</table>
-<p id="footer">semver — npm@2.3.0</p>
+<p id="footer">semver — npm@2.4.1</p>
<p>If you have a complaint about a package in the public npm registry,
and cannot <a href="https://docs.npmjs.com/misc/disputes">resolve it with the package
owner</a>, please email
-<a href="mailto:support@npmjs.com">support@npmjs.com</a> and explain the situation.</p>
+<a href="mailto:support@npmjs.com">support@npmjs.com</a> and explain the situation.</p>
<p>Any data published to The npm Registry (including user account
information) may be removed or modified at the sole discretion of the
npm server administrators.</p>
npm.commands.install(["package"], cb)
})
</code></pre><h2 id="version">VERSION</h2>
-<p>2.3.0</p>
+<p>2.4.1</p>
<h2 id="description">DESCRIPTION</h2>
<p>This is the API documentation for npm.
To find documentation of the command line
--- /dev/null
+<h1><a href="../cli/npm-access.html">npm-access</a></h1> <p>Set access level on published packages</p>
+<h2 id="synopsis">SYNOPSIS</h2>
+<pre><code>npm access public [<package>]
+npm access restricted [<package>]
+
+npm access add <read-only|read-write> <entity> [<package>]
+npm access rm <entity> [<package>]
+
+npm access ls [<package>]
+npm access edit [<package>]
+</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>Used to set access controls on private packages.</p>
+<p>For all of the subcommands, <code>npm access</code> will perform actions on the packages
+in the current working directory if no package name is passed to the
+subcommand.</p>
+<ul>
+<li><p>public / restricted:
+Set a package to be either publicly accessible or restricted.</p>
+</li>
+<li><p>add / rm:
+Add or remove the ability of users and teams to have read-only or read-write
+access to a package.</p>
+</li>
+<li><p>ls:
+Show all of the access privileges for a package. Will only show permissions
+for packages to which you have at least read access.</p>
+</li>
+<li><p>edit:
+Set the access privileges for a package at once using <code>$EDITOR</code>.</p>
+</li>
+</ul>
+<h2 id="details">DETAILS</h2>
+<p><code>npm access</code> always operates directly on the current registry, configurable
+from the command line using <code>--registry=<registry url></code>.</p>
+<p>Unscoped packages are <em>always public</em>.</p>
+<p>Scoped packages <em>default to restricted</em>, but you can either publish them as
+public using <code>npm publish --access=public</code>, or set their access as public using
+<code>npm access public</code> after the initial publish.</p>
+<p>You must have privileges to set the access of a package:</p>
+<ul>
+<li>You are an owner of an unscoped or scoped package.</li>
+<li>You are a member of the team that owns a scope.</li>
+<li>You have been given read-write privileges for a package, either as a member
+of a team or directly as an owner.</li>
+</ul>
+<p>If your account is not paid, then attempts to publish scoped packages will fail
+with an HTTP 402 status code (logically enough), unless you use
+<code>--access=public</code>.</p>
+<h2 id="see-also">SEE ALSO</h2>
+<ul>
+<li><a href="../cli/npm-publish.html">npm-publish(1)</a></li>
+<li><a href="../misc/npm-config.html">npm-config(7)</a></li>
+<li><a href="../misc/npm-registry.html">npm-registry(7)</a></li>
+</ul>
--- /dev/null
+<h1><a href="../cli/npm-dist-tag.html">npm-dist-tag</a></h1> <p>Modify package distribution tags</p>
+<h2 id="synopsis">SYNOPSIS</h2>
+<pre><code>npm dist-tag add <pkg>@<version> [<tag>]
+npm dist-tag rm <pkg> <tag>
+npm dist-tag ls [<pkg>]
+</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>Add, remove, and enumerate distribution tags on a package:</p>
+<ul>
+<li><p>add:
+Tags the specified version of the package with the specified tag, or the
+<code>--tag</code> config if not specified.</p>
+</li>
+<li><p>rm:
+Clear a tag that is no longer in use from the package.</p>
+</li>
+<li><p>ls:
+Show all of the dist-tags for a package, defaulting to the package in
+the curren prefix.</p>
+</li>
+</ul>
+<p>A tag can be used when installing packages as a reference to a version instead
+of using a specific version number:</p>
+<pre><code>npm install <name>@<tag>
+</code></pre><p>When installing dependencies, a preferred tagged version may be specified:</p>
+<pre><code>npm install --tag <tag>
+</code></pre><p>This also applies to <code>npm dedupe</code>.</p>
+<p>Publishing a package always sets the "latest" tag to the published version.</p>
+<h2 id="purpose">PURPOSE</h2>
+<p>Tags can be used to provide an alias instead of version numbers. For
+example, <code>npm</code> currently uses the tag "next" to identify the upcoming
+version, and the tag "latest" to identify the current version.</p>
+<p>A project might choose to have multiple streams of development, e.g.,
+"stable", "canary".</p>
+<h2 id="caveats">CAVEATS</h2>
+<p>This command used to be known as <code>npm tag</code>, which only created new tags, and so
+had a different syntax.</p>
+<p>Tags must share a namespace with version numbers, because they are specified in
+the same slot: <code>npm install <pkg>@<version></code> vs <code>npm install <pkg>@<tag></code>.</p>
+<p>Tags that can be interpreted as valid semver ranges will be rejected. For
+example, <code>v1.4</code> cannot be used as a tag, because it is interpreted by semver as
+<code>>=1.4.0 <1.5.0</code>. See <a href="https://github.com/npm/npm/issues/6082">https://github.com/npm/npm/issues/6082</a>.</p>
+<p>The simplest way to avoid semver problems with tags is to use tags that do not
+begin with a number or the letter <code>v</code>.</p>
+<h2 id="see-also">SEE ALSO</h2>
+<ul>
+<li><a href="../cli/npm-tag.html">npm-tag(1)</a></li>
+<li><a href="../cli/npm-publish.html">npm-publish(1)</a></li>
+<li><a href="../cli/npm-install.html">npm-install(1)</a></li>
+<li><a href="../cli/npm-dedupe.html">npm-dedupe(1)</a></li>
+<li><a href="../misc/npm-registry.html">npm-registry(7)</a></li>
+<li><a href="../cli/npm-config.html">npm-config(1)</a></li>
+<li><a href="../misc/npm-config.html">npm-config(7)</a></li>
+<li><a href="../api/npm-tag.html">npm-tag(3)</a></li>
+<li><a href="../files/npmrc.html">npmrc(5)</a></li>
+</ul>
limit the results to only the paths to the packages named. Note that
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@2.3.0 /path/to/npm
+<pre><code>npm@2.4.1 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre><p>It will print out extraneous, missing, and invalid packages.</p>
<h1><a href="../cli/npm-publish.html">npm-publish</a></h1> <p>Publish a package</p>
<h2 id="synopsis">SYNOPSIS</h2>
-<pre><code>npm publish <tarball> [--tag <tag>]
-npm publish <folder> [--tag <tag>]
+<pre><code>npm publish <tarball> [--tag <tag>] [--access <public|restricted>]
+npm publish <folder> [--tag <tag>] [--access <public|restricted>]
</code></pre><h2 id="description">DESCRIPTION</h2>
<p>Publishes a package to the registry so that it can be installed by name. See
<code><a href="../misc/npm-developers.html">npm-developers(7)</a></code> for details on what's included in the published package, as
<name>@<tag></code> will install this version. By default, <code>npm publish</code> updates
and <code>npm install</code> installs the <code>latest</code> tag.</p>
</li>
+<li><p><code>[--access <public|restricted>]</code>
+Tells the registry whether this package should be published as public or
+restricted. Only applies to scoped packages, which default to <code>restricted</code>.
+If you don't have a paid account, you must publish with <code>--access public</code>
+to publish scoped packages.</p>
+</li>
</ul>
<p>Fails if the package name and version combination already exists in
the specified registry.</p>
<h2 id="see-also">SEE ALSO</h2>
<ul>
<li><a href="../misc/npm-registry.html">npm-registry(7)</a></li>
+<li><a href="../misc/npm-scope.html">npm-scope(7)</a></li>
<li><a href="../cli/npm-adduser.html">npm-adduser(1)</a></li>
<li><a href="../cli/npm-owner.html">npm-owner(1)</a></li>
<li><a href="../cli/npm-deprecate.html">npm-deprecate(1)</a></li>
<h2 id="synopsis">SYNOPSIS</h2>
<pre><code>npm tag <name>@<version> [<tag>]
</code></pre><h2 id="description">DESCRIPTION</h2>
+<p>THIS COMMAND IS DEPRECATED. See <a href="../cli/npm-dist-tag.html">npm-dist-tag(1)</a> for details.</p>
<p>Tags the specified version of the package with the specified tag, or the
<code>--tag</code> config if not specified.</p>
<p>A tag can be used when installing packages as a reference to a version instead
<h2 id="synopsis">SYNOPSIS</h2>
<pre><code>npm <command> [args]
</code></pre><h2 id="version">VERSION</h2>
-<p>2.3.0</p>
+<p>2.4.1</p>
<h2 id="description">DESCRIPTION</h2>
<p>npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency
the issues list or ask on the mailing list.</p>
<ul>
<li><a href="http://github.com/npm/npm/issues">http://github.com/npm/npm/issues</a></li>
-<li><a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
+<li><a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
</ul>
<h2 id="bugs">BUGS</h2>
<p>When you find issues, please report them:</p>
<li>web:
<a href="http://github.com/npm/npm/issues">http://github.com/npm/npm/issues</a></li>
<li>email:
-<a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
+<a href="mailto:npm-@googlegroups.com">npm-@googlegroups.com</a></li>
</ul>
<p>Be sure to include <em>all</em> of the output from the npm command that didn't work
as expected. The <code>npm-debug.log</code> file is also helpful to provide.</p>
<p><a href="http://blog.izs.me/">Isaac Z. Schlueter</a> ::
<a href="https://github.com/isaacs/">isaacs</a> ::
<a href="http://twitter.com/izs">@izs</a> ::
-<a href="mailto:i@izs.me">i@izs.me</a></p>
+<a href="mailto:i@izs.me">i@izs.me</a></p>
<h2 id="see-also">SEE ALSO</h2>
<ul>
<li><a href="../cli/npm-help.html">npm-help(1)</a></li>
<p>Using npm on the command line</p>
<h3 id="npm-1-"><a href="cli/npm.html">npm(1)</a></h3>
<p>javascript package manager</p>
+<h3 id="npm-access-1-"><a href="cli/npm-access.html">npm-access(1)</a></h3>
+<p>Set access level on published packages</p>
<h3 id="npm-adduser-1-"><a href="cli/npm-adduser.html">npm-adduser(1)</a></h3>
<p>Add a registry user account</p>
<h3 id="npm-bin-1-"><a href="cli/npm-bin.html">npm-bin(1)</a></h3>
<p>Reduce duplication</p>
<h3 id="npm-deprecate-1-"><a href="cli/npm-deprecate.html">npm-deprecate(1)</a></h3>
<p>Deprecate a version of a package</p>
+<h3 id="npm-dist-tag-1-"><a href="cli/npm-dist-tag.html">npm-dist-tag(1)</a></h3>
+<p>Modify package distribution tags</p>
<h3 id="npm-docs-1-"><a href="cli/npm-docs.html">npm-docs(1)</a></h3>
<p>Docs for a package in a web browser maybe</p>
<h3 id="npm-edit-1-"><a href="cli/npm-edit.html">npm-edit(1)</a></h3>
<pre><code>npm config set foo:port 80
</code></pre><p>See <a href="../files/package.json.html">package.json(5)</a> for more information.</p>
<h2 id="config-settings">Config Settings</h2>
+<h3 id="access">access</h3>
+<ul>
+<li>Default: <code>restricted</code></li>
+<li>Type: Access</li>
+</ul>
+<p>When publishing scoped packages, the access level defaults to <code>restricted</code>. If
+you want your scoped package to be publicly viewable (and installable) set
+<code>--access=public</code>. The only valid values for <code>access</code> are <code>public</code> and
+<code>restricted</code>. Unscoped packages <em>always</em> have an access level of <code>public</code>.</p>
<h3 id="always-auth">always-auth</h3>
<ul>
<li>Default: false</li>
<h2 id="synopsis">SYNOPSIS</h2>
<ol>
<li>Get the author email with <code>npm owner ls <pkgname></code></li>
-<li>Email the author, CC <a href="mailto:support@npmjs.com">support@npmjs.com</a></li>
+<li>Email the author, CC <a href="mailto:support@npmjs.com">support@npmjs.com</a></li>
<li>After a few weeks, if there's no resolution, we'll sort it out.</li>
</ol>
<p>Don't squat on package names. Publish code or move out of the way.</p>
owner (Bob).</li>
<li>Joe emails Bob, explaining the situation <strong>as respectfully as
possible</strong>, and what he would like to do with the module name. He
-adds the npm support staff <a href="mailto:support@npmjs.com">support@npmjs.com</a> to the CC list of
+adds the npm support staff <a href="mailto:support@npmjs.com">support@npmjs.com</a> to the CC list of
the email. Mention in the email that Bob can run <code>npm owner add
joe foo</code> to add Joe as an owner of the <code>foo</code> package.</li>
<li>After a reasonable amount of time, if Bob has not responded, or if
Bob and Joe can't come to any sort of resolution, email support
-<a href="mailto:support@npmjs.com">support@npmjs.com</a> and we'll sort it out. ("Reasonable" is
+<a href="mailto:support@npmjs.com">support@npmjs.com</a> and we'll sort it out. ("Reasonable" is
usually at least 4 weeks, but extra time is allowed around common
holidays.)</li>
</ol>
<p>To check if the registry is down, open up
<a href="https://registry.npmjs.org/">https://registry.npmjs.org/</a> in a web browser. This will also tell
you if you are just unable to access the internet for some reason.</p>
-<p>If the registry IS down, let us know by emailing <a href="mailto:support@npmjs.com">support@npmjs.com</a>
+<p>If the registry IS down, let us know by emailing <a href="mailto:support@npmjs.com">support@npmjs.com</a>
or posting an issue at <a href="https://github.com/npm/npm/issues">https://github.com/npm/npm/issues</a>. If it's
down for the world (and not just on your local network) then we're
probably already being pinged about it.</p>
<p>Using npm on the command line</p>
<h3 id="npm-1-"><a href="../cli/npm.html">npm(1)</a></h3>
<p>javascript package manager</p>
+<h3 id="npm-access-1-"><a href="../cli/npm-access.html">npm-access(1)</a></h3>
+<p>Set access level on published packages</p>
<h3 id="npm-adduser-1-"><a href="../cli/npm-adduser.html">npm-adduser(1)</a></h3>
<p>Add a registry user account</p>
<h3 id="npm-bin-1-"><a href="../cli/npm-bin.html">npm-bin(1)</a></h3>
<p>Reduce duplication</p>
<h3 id="npm-deprecate-1-"><a href="../cli/npm-deprecate.html">npm-deprecate(1)</a></h3>
<p>Deprecate a version of a package</p>
+<h3 id="npm-dist-tag-1-"><a href="../cli/npm-dist-tag.html">npm-dist-tag(1)</a></h3>
+<p>Modify package distribution tags</p>
<h3 id="npm-docs-1-"><a href="../cli/npm-docs.html">npm-docs(1)</a></h3>
<p>Docs for a package in a web browser maybe</p>
<h3 id="npm-edit-1-"><a href="../cli/npm-edit.html">npm-edit(1)</a></h3>
--- /dev/null
+var assert = require("assert")
+var resolve = require("path").resolve
+var url = require("url")
+
+var log = require("npmlog")
+var readPackageJson = require("read-package-json")
+
+var mapToRegistry = require("./utils/map-to-registry.js")
+var npa = require("npm-package-arg")
+var npm = require("./npm.js")
+
+module.exports = access
+
+access.usage = "npm access public [<package>]"
+ + "\nnpm access restricted [<package>]"
+ + "\nnpm access add <read-only|read-write> <entity> [<package>]"
+ + "\nnpm access rm <entity> [<package>]"
+ + "\nnpm access ls [<package>]"
+ + "\nnpm access edit [<package>]"
+
+access.completion = function (opts, cb) {
+ var argv = opts.conf.argv.remain
+ if (argv.length === 2) {
+ return cb(null, ["public", "restricted", "add", "rm", "ls", "edit"])
+ }
+
+ switch (argv[2]) {
+ case "public":
+ case "restricted":
+ case "ls":
+ case "edit":
+ return cb(new Error("unimplemented: packages you can change"))
+ case "add":
+ if (argv.length === 3) return cb(null, ["read-only", "read-write"])
+
+ return cb(new Error("unimplemented: entities and packages"))
+ case "rm":
+ return cb(new Error("unimplemented: entities and packages"))
+ default:
+ return cb(new Error(argv[2]+" not recognized"))
+ }
+}
+
+function access (args, cb) {
+ var cmd = args.shift()
+ switch (cmd) {
+ case "public": case "restricted": return changeAccess(args, cmd, cb)
+ case "add": case "set": return add(args, cb)
+ case "rm": case "del": case "clear": return rm(args, cb)
+ case "list": case "sl": case "ls": return ls(args, cb)
+ case "edit": case "ed": return edit(args, cb)
+ default: return cb("Usage:\n"+access.usage)
+ }
+}
+
+function changeAccess (args, level, cb) {
+ assert(Array.isArray(args), "changeAccess requires args be an array")
+ assert(
+ ["public", "restricted"].indexOf(level) !== -1,
+ "access level must be either 'public' or 'restricted'"
+ )
+ assert(typeof cb === "function", "changeAccess requires a callback")
+
+ var p = (args.shift() || "").trim()
+ if (!p) return getCurrentPackage(level, cb)
+ changeAccess_(p, level, cb)
+}
+
+function getCurrentPackage (level, cb) {
+ var here = resolve(npm.prefix, "package.json")
+ log.verbose("setPackageLevel", "here", here)
+
+ readPackageJson(here, function (er, data) {
+ if (er) return cb(er)
+
+ if (!data.name) {
+ return cb(new Error("Package must be named"))
+ }
+
+ changeAccess_(data.name, level, cb)
+ })
+}
+
+function changeAccess_ (name, level, cb) {
+ log.verbose("changeAccess", "name", name, "level", level)
+ mapToRegistry(name, npm.config, function (er, uri, auth, base) {
+ if (er) return cb(er)
+
+ var data = npa(name)
+ if (!data.scope) {
+ var msg = "Sorry, you can't change the access level of unscoped packages."
+ log.error("access", msg)
+ return cb(new Error(msg))
+ }
+
+ // name must be scoped, so escape separator
+ name = name.replace("/", "%2f")
+ // FIXME: mapToRegistry still isn't generic enough SIGH
+ uri = url.resolve(base, "-/package/"+name+"/access")
+ var params = {
+ level : level,
+ auth : auth
+ }
+
+ npm.registry.access(uri, params, cb)
+ })
+}
+
+function add (args, cb) {
+ return cb(new Error("npm access add isn't implemented yet!"))
+}
+
+function rm (args, cb) {
+ return cb(new Error("npm access rm isn't implemented yet!"))
+}
+
+function ls (args, cb) {
+ return cb(new Error("npm access ls isn't implemented yet!"))
+}
+
+function edit (args, cb) {
+ return cb(new Error("npm edit ls isn't implemented yet!"))
+}
// swizzle in our custom cache invalidation logic
this._request = this.request
this.request = this._invalidatingRequest
+ this.get = get
}
inherits(CachingRegistryClient, RegistryClient)
// thinking that it didn't work when it did.
// Note that failure is an acceptable option here, since the only
// result will be a stale cache for some helper commands.
- client.log.verbose("request", "invalidating", invalidated, "on", method)
+ log.verbose("request", "invalidating", invalidated, "on", method)
return rimraf(invalidated, function () {
cb.apply(undefined, args)
})
})
}
-CachingRegistryClient.prototype.get = function get (uri, params, cb) {
+function get (uri, params, cb) {
assert(typeof uri === "string", "must pass registry URI to get")
assert(params && typeof params === "object", "must pass params to get")
assert(typeof cb === "function", "must pass callback to get")
// If the GET is part of a write operation (PUT or DELETE), then
// skip past the cache entirely, but still save the results.
- if (uri.match(/\?write=true$/)) return get_.call(this, uri, cachePath, params, cb)
+ if (uri.match(/\?write=true$/)) {
+ log.verbose("get", "GET as part of write; not caching result")
+ return get_.call(this, uri, cachePath, params, cb)
+ }
var client = this
fs.stat(cachePath, function (er, stat) {
}
function saveToCache (cachePath, data, saved) {
+ log.verbose("get", "saving", data.name, "to", cachePath)
getCacheStat(function (er, st) {
mkdirp(path.dirname(cachePath), function (er, made) {
if (er) return saved()
exports.Umask = Umask
function Umask () {}
function validateUmask (data, k, val) {
- return umask.validate (data, k, val)
+ return umask.validate(data, k, val)
}
function validateSemver (data, k, val) {
}
defaults = {
- "always-auth" : false
+ access : "restricted"
+ , "always-auth" : false
+
, "bin-links" : true
, browser : null
}})
exports.types =
- { "always-auth" : Boolean
+ { access : ["restricted", "public"]
+ , "always-auth" : Boolean
, "bin-links": Boolean
, browser : [null, String]
, ca: [null, String, Array]
// local-address must be listed as an IP for a local network interface
// must be IPv4 due to node bug
, "local-address" : getLocalAddresses()
- , loglevel : ["silent","error","warn","http","info","verbose","silly"]
+ , loglevel : ["silent", "error", "warn", "http", "info", "verbose", "silly"]
, logstream : Stream
, long : Boolean
, message: String
--- /dev/null
+module.exports = distTag
+
+var log = require("npmlog")
+var npa = require("npm-package-arg")
+var semver = require("semver")
+
+var npm = require("./npm.js")
+var mapToRegistry = require("./utils/map-to-registry.js")
+var readLocalPkg = require("./utils/read-local-package.js")
+
+distTag.usage = "npm dist-tag add <pkg>@<version> [<tag>]"
+ + "\nnpm dist-tag rm <pkg> <tag>"
+ + "\nnpm dist-tag ls [<pkg>]"
+
+distTag.completion = function (opts, cb) {
+ var argv = opts.conf.argv.remain
+ if (argv.length === 2) {
+ return cb(null, ["add", "rm", "ls"])
+ }
+
+ switch (argv[2]) {
+ default:
+ return cb()
+ }
+}
+
+function distTag (args, cb) {
+ var cmd = args.shift()
+ switch (cmd) {
+ case "add": case "a": case "set": case "s":
+ return add(args[0], args[1], cb)
+ case "rm": case "r": case "del": case "d": case "remove":
+ return remove(args[1], args[0], cb)
+ case "ls": case "l": case "sl": case "list":
+ return list(args[0], cb)
+ default:
+ return cb("Usage:\n"+distTag.usage)
+ }
+}
+
+function add (spec, tag, cb) {
+ var thing = npa(spec || "")
+ var pkg = thing.name
+ var version = thing.rawSpec
+ var t = (tag || npm.config.get("tag")).trim()
+
+ log.verbose("dist-tag add", t, "to", pkg+"@"+version)
+
+ if (!pkg || !version || !t) return cb("Usage:\n"+distTag.usage)
+
+ if (semver.validRange(t)) {
+ var er = new Error("Tag name must not be a valid SemVer range: " + t)
+ return cb(er)
+ }
+
+ fetchTags(pkg, function (er, tags) {
+ if (er) return cb(er)
+
+ if (tags[t] === version) {
+ log.warn("dist-tag add", t, "is already set to version", version)
+ return cb()
+ }
+ tags[t] = version
+
+ mapToRegistry(pkg, npm.config, function (er, uri, auth, base) {
+ var params = {
+ package : pkg,
+ distTag : t,
+ version : version,
+ auth : auth
+ }
+
+ npm.registry.distTags.add(base, params, function (er) {
+ if (er) return cb(er)
+
+ console.log("+"+t+": "+pkg+"@"+version)
+ cb()
+ })
+ })
+ })
+}
+
+function remove (tag, pkg, cb) {
+ log.verbose("dist-tag del", tag, "from", pkg)
+
+ fetchTags(pkg, function (er, tags) {
+ if (er) return cb(er)
+
+ if (!tags[tag]) {
+ log.info("dist-tag del", tag, "is not a dist-tag on", pkg)
+ return cb(new Error(tag+" is not a dist-tag on "+pkg))
+ }
+
+ var version = tags[tag]
+ delete tags[tag]
+
+ mapToRegistry(pkg, npm.config, function (er, uri, auth, base) {
+ var params = {
+ package : pkg,
+ distTag : tag,
+ auth : auth
+ }
+
+ npm.registry.distTags.rm(base, params, function (er) {
+ if (er) return cb(er)
+
+ console.log("-"+tag+": "+pkg+"@"+version)
+ cb()
+ })
+ })
+ })
+}
+
+function list (pkg, cb) {
+ if (!pkg) return readLocalPkg(function (er, pkg) {
+ if (er) return cb(er)
+ if (!pkg) return cb(distTag.usage)
+ list(pkg, cb)
+ })
+
+ fetchTags(pkg, function (er, tags) {
+ if (er) {
+ log.error("dist-tag ls", "Couldn't get dist-tag data for", pkg)
+ return cb(er)
+ }
+ var msg = Object.keys(tags).map(function (k) {
+ return k+": "+tags[k]
+ }).sort().join("\n")
+ console.log(msg)
+ cb(er, tags)
+ })
+}
+
+function fetchTags (pkg, cb) {
+ mapToRegistry(pkg, npm.config, function (er, uri, auth, base) {
+ if (er) return cb(er)
+
+ var params = {
+ package : pkg,
+ auth : auth
+ }
+ npm.registry.distTags.fetch(base, params, function (er, tags) {
+ if (er) return cb(er)
+ if (!tags || !Object.keys(tags).length) {
+ return cb(new Error("No dist-tags found for " + pkg))
+ }
+
+ cb(null, tags)
+ })
+ })
+}
, "isntall" : "install"
, "up" : "update"
, "c" : "config"
+ , "dist-tags" : "dist-tag"
, "info" : "view"
, "show" : "view"
, "find" : "search"
, "adduser"
, "unpublish"
, "owner"
+ , "access"
, "deprecate"
, "shrinkwrap"
, "prefix"
, "bin"
, "whoami"
+ , "dist-tag"
, "test"
, "stop"
var npm = require("./npm.js")
, log = require("npmlog")
- , readJson = require("read-package-json")
, mapToRegistry = require("./utils/map-to-registry.js")
+ , readLocalPkg = require("./utils/read-local-package.js")
owner.completion = function (opts, cb) {
var argv = opts.conf.argv.remain
}
}
-function readLocalPkg (cb) {
- if (npm.config.get("global")) return cb()
- var path = require("path")
- readJson(path.resolve(npm.prefix, "package.json"), function (er, d) {
- return cb(er, d && d.name)
- })
-}
-
function unknown (action, cb) {
cb("Usage: \n" + owner.usage)
}
, mapToRegistry = require("./utils/map-to-registry.js")
, cachedPackageRoot = require("./cache/cached-package-root.js")
, createReadStream = require("graceful-fs").createReadStream
+ , npa = require("npm-package-arg")
publish.usage = "npm publish <tarball>"
+ "\nnpm publish <folder>"
auth : auth
}
+ // registry-frontdoor cares about the access level, which is only
+ // configurable for scoped packages
+ if (npa(data.name).scope) {
+ params.access = config.get("access")
+ }
+ else {
+ params.access = "public"
+ }
+
registry.publish(registryBase, params, function (er) {
if (er && er.code === "EPUBLISHCONFLICT" &&
npm.config.get("force") && !isRetry) {
, mapToRegistry = require("./utils/map-to-registry.js")
, npa = require("npm-package-arg")
, semver = require("semver")
+ , log = require("npmlog")
function tag (args, cb) {
var thing = npa(args.shift() || "")
return cb(er)
}
+ log.warn("tag", "This command is deprecated. Use `npm dist-tag` instead.")
+
mapToRegistry(project, npm.config, function (er, uri, auth) {
if (er) return cb(er)
, gentlyRm = require("./utils/gently-rm.js")
, npm = require("./npm.js")
, path = require("path")
+ , isInside = require("path-is-inside")
, lifecycle = require("./utils/lifecycle.js")
, asyncMap = require("slide").asyncMap
, chain = require("slide").chain
cb_(er, path.relative(npm.root, folder))
}
folder = path.resolve(folder)
+ var base = isInside(folder, npm.prefix) ? npm.prefix : folder
delete build._didBuild[folder]
log.verbose("unbuild", folder.substr(npm.prefix.length + 1))
readJson(path.resolve(folder, "package.json"), function (er, pkg) {
// if no json, then just trash it, but no scripts or whatever.
- if (er) return gentlyRm(folder, false, npm.prefix, cb)
+ if (er) return gentlyRm(folder, false, base, cb)
readJson.cache.del(folder)
chain
( [ [lifecycle, pkg, "preuninstall", folder, false, true]
}
, [rmStuff, pkg, folder]
, [lifecycle, pkg, "postuninstall", folder, false, true]
- , [gentlyRm, folder, false, npm.prefix] ]
+ , [gentlyRm, folder, false, base] ]
, cb )
})
}}
--- /dev/null
+exports = module.exports = readLocalPkg
+
+var npm = require("../npm.js")
+ , readJson = require("read-package-json")
+
+function readLocalPkg (cb) {
+ if (npm.config.get("global")) return cb()
+ var path = require("path")
+ readJson(path.resolve(npm.prefix, "package.json"), function (er, d) {
+ return cb(er, d && d.name)
+ })
+}
--- /dev/null
+.TH "NPM\-ACCESS" "1" "January 2015" "" ""
+.SH "NAME"
+\fBnpm-access\fR \- Set access level on published packages
+.SH SYNOPSIS
+.P
+.RS 2
+.nf
+npm access public [<package>]
+npm access restricted [<package>]
+
+npm access add <read\-only|read\-write> <entity> [<package>]
+npm access rm <entity> [<package>]
+
+npm access ls [<package>]
+npm access edit [<package>]
+.fi
+.RE
+.SH DESCRIPTION
+.P
+Used to set access controls on private packages\.
+.P
+For all of the subcommands, \fBnpm access\fR will perform actions on the packages
+in the current working directory if no package name is passed to the
+subcommand\.
+.RS 0
+.IP \(bu 2
+public / restricted:
+Set a package to be either publicly accessible or restricted\.
+.IP \(bu 2
+add / rm:
+Add or remove the ability of users and teams to have read\-only or read\-write
+access to a package\.
+.IP \(bu 2
+ls:
+Show all of the access privileges for a package\. Will only show permissions
+for packages to which you have at least read access\.
+.IP \(bu 2
+edit:
+Set the access privileges for a package at once using \fB$EDITOR\fR\|\.
+
+.RE
+.SH DETAILS
+.P
+\fBnpm access\fR always operates directly on the current registry, configurable
+from the command line using \fB\-\-registry=<registry url>\fR\|\.
+.P
+Unscoped packages are \fIalways public\fR\|\.
+.P
+Scoped packages \fIdefault to restricted\fR, but you can either publish them as
+public using \fBnpm publish \-\-access=public\fR, or set their access as public using
+\fBnpm access public\fR after the initial publish\.
+.P
+You must have privileges to set the access of a package:
+.RS 0
+.IP \(bu 2
+You are an owner of an unscoped or scoped package\.
+.IP \(bu 2
+You are a member of the team that owns a scope\.
+.IP \(bu 2
+You have been given read\-write privileges for a package, either as a member
+of a team or directly as an owner\.
+
+.RE
+.P
+If your account is not paid, then attempts to publish scoped packages will fail
+with an HTTP 402 status code (logically enough), unless you use
+\fB\-\-access=public\fR\|\.
+.SH SEE ALSO
+.RS 0
+.IP \(bu 2
+npm help publish
+.IP \(bu 2
+npm help 7 config
+.IP \(bu 2
+npm help 7 registry
+
+.RE
--- /dev/null
+.TH "NPM\-DIST\-TAG" "1" "January 2015" "" ""
+.SH "NAME"
+\fBnpm-dist-tag\fR \- Modify package distribution tags
+.SH SYNOPSIS
+.P
+.RS 2
+.nf
+npm dist\-tag add <pkg>@<version> [<tag>]
+npm dist\-tag rm <pkg> <tag>
+npm dist\-tag ls [<pkg>]
+.fi
+.RE
+.SH DESCRIPTION
+.P
+Add, remove, and enumerate distribution tags on a package:
+.RS 0
+.IP \(bu 2
+add:
+Tags the specified version of the package with the specified tag, or the
+\fB\-\-tag\fR config if not specified\.
+.IP \(bu 2
+rm:
+Clear a tag that is no longer in use from the package\.
+.IP \(bu 2
+ls:
+Show all of the dist\-tags for a package, defaulting to the package in
+the curren prefix\.
+
+.RE
+.P
+A tag can be used when installing packages as a reference to a version instead
+of using a specific version number:
+.P
+.RS 2
+.nf
+npm install <name>@<tag>
+.fi
+.RE
+.P
+When installing dependencies, a preferred tagged version may be specified:
+.P
+.RS 2
+.nf
+npm install \-\-tag <tag>
+.fi
+.RE
+.P
+This also applies to \fBnpm dedupe\fR\|\.
+.P
+Publishing a package always sets the "latest" tag to the published version\.
+.SH PURPOSE
+.P
+Tags can be used to provide an alias instead of version numbers\. For
+example, \fBnpm\fR currently uses the tag "next" to identify the upcoming
+version, and the tag "latest" to identify the current version\.
+.P
+A project might choose to have multiple streams of development, e\.g\.,
+"stable", "canary"\.
+.SH CAVEATS
+.P
+This command used to be known as \fBnpm tag\fR, which only created new tags, and so
+had a different syntax\.
+.P
+Tags must share a namespace with version numbers, because they are specified in
+the same slot: \fBnpm install <pkg>@<version>\fR vs \fBnpm install <pkg>@<tag>\fR\|\.
+.P
+Tags that can be interpreted as valid semver ranges will be rejected\. For
+example, \fBv1\.4\fR cannot be used as a tag, because it is interpreted by semver as
+\fB>=1\.4\.0 <1\.5\.0\fR\|\. See https://github\.com/npm/npm/issues/6082\|\.
+.P
+The simplest way to avoid semver problems with tags is to use tags that do not
+begin with a number or the letter \fBv\fR\|\.
+.SH SEE ALSO
+.RS 0
+.IP \(bu 2
+npm help tag
+.IP \(bu 2
+npm help publish
+.IP \(bu 2
+npm help install
+.IP \(bu 2
+npm help dedupe
+.IP \(bu 2
+npm help 7 registry
+.IP \(bu 2
+npm help config
+.IP \(bu 2
+npm help 7 config
+.IP \(bu 2
+npm apihelp tag
+.IP \(bu 2
+npm help 5 npmrc
+
+.RE
.P
.RS 2
.nf
-npm@2.3.0 /path/to/npm
+npm@2.4.1 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi
.P
.RS 2
.nf
-npm publish <tarball> [\-\-tag <tag>]
-npm publish <folder> [\-\-tag <tag>]
+npm publish <tarball> [\-\-tag <tag>] [\-\-access <public|restricted>]
+npm publish <folder> [\-\-tag <tag>] [\-\-access <public|restricted>]
.fi
.RE
.SH DESCRIPTION
Registers the published package with the given tag, such that \fBnpm install
<name>@<tag>\fR will install this version\. By default, \fBnpm publish\fR updates
and \fBnpm install\fR installs the \fBlatest\fR tag\.
+.IP \(bu 2
+\fB[\-\-access <public|restricted>]\fR
+Tells the registry whether this package should be published as public or
+restricted\. Only applies to scoped packages, which default to \fBrestricted\fR\|\.
+If you don't have a paid account, you must publish with \fB\-\-access public\fR
+to publish scoped packages\.
.RE
.P
.IP \(bu 2
npm help 7 registry
.IP \(bu 2
+npm help 7 scope
+.IP \(bu 2
npm help adduser
.IP \(bu 2
npm help owner
.RE
.SH DESCRIPTION
.P
+THIS COMMAND IS DEPRECATED\. See npm help dist\-tag for details\.
+.P
Tags the specified version of the package with the specified tag, or the
\fB\-\-tag\fR config if not specified\.
.P
.RE
.SH VERSION
.P
-2.3.0
+2.4.1
.SH DESCRIPTION
.P
npm is the package manager for the Node JavaScript platform\. It puts
.RE
.SH VERSION
.P
-2.3.0
+2.4.1
.SH DESCRIPTION
.P
This is the API documentation for npm\.
.P
See npm help 5 package\.json for more information\.
.SH Config Settings
+.SS access
+.RS 0
+.IP \(bu 2
+Default: \fBrestricted\fR
+.IP \(bu 2
+Type: Access
+
+.RE
+.P
+When publishing scoped packages, the access level defaults to \fBrestricted\fR\|\. If
+you want your scoped package to be publicly viewable (and installable) set
+\fB\-\-access=public\fR\|\. The only valid values for \fBaccess\fR are \fBpublic\fR and
+\fBrestricted\fR\|\. Unscoped packages \fIalways\fR have an access level of \fBpublic\fR\|\.
.SS always\-auth
.RS 0
.IP \(bu 2
.SS npm help npm
.P
javascript package manager
+.SS npm help access
+.P
+Set access level on published packages
.SS npm help adduser
.P
Add a registry user account
.SS npm help deprecate
.P
Deprecate a version of a package
+.SS npm help dist\-tag
+.P
+Modify package distribution tags
.SS npm help docs
.P
Docs for a package in a web browser maybe
try { p = JSON.parse(p) }
catch (e) { return next() }
if (!p.version) return next()
- deps[d] = config.get('save-prefix') + p.version
+ deps[d] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
return next()
})
})
"tarball": "http://registry.npmjs.org/promzard/-/promzard-0.2.2.tgz"
},
"directories": {},
- "_resolved": "https://registry.npmjs.org/promzard/-/promzard-0.2.2.tgz"
+ "_resolved": "https://registry.npmjs.org/promzard/-/promzard-0.2.2.tgz",
+ "readme": "ERROR: No README data found!"
}
{
"name": "init-package-json",
- "version": "1.1.3",
+ "version": "1.2.0",
"main": "init-package-json.js",
"scripts": {
"test": "tap test/*.js"
"prompt",
"start"
],
- "readme": "# init-package-json\n\nA node module to get your node module started.\n\n## Usage\n\n```javascript\nvar init = require('init-package-json')\nvar path = require('path')\n\n// a path to a promzard module. In the event that this file is\n// not found, one will be provided for you.\nvar initFile = path.resolve(process.env.HOME, '.npm-init')\n\n// the dir where we're doin stuff.\nvar dir = process.cwd()\n\n// extra stuff that gets put into the PromZard module's context.\n// In npm, this is the resolved config object. Exposed as 'config'\n// Optional.\nvar configData = { some: 'extra stuff' }\n\n// Any existing stuff from the package.json file is also exposed in the\n// PromZard module as the `package` object. There will also be free\n// vars for:\n// * `filename` path to the package.json file\n// * `basename` the tip of the package dir\n// * `dirname` the parent of the package dir\n\ninit(dir, initFile, configData, function (er, data) {\n // the data's already been written to {dir}/package.json\n // now you can do stuff with it\n})\n```\n\nOr from the command line:\n\n```\n$ npm-init\n```\n\nSee [PromZard](https://github.com/isaacs/promzard) for details about\nwhat can go in the config file.\n",
- "readmeFilename": "README.md",
- "gitHead": "b766900b2d615ddc43c452e251b8c5543538e832",
+ "gitHead": "6c0743199706494a190c0b47d2e2567dc86055a3",
"bugs": {
"url": "https://github.com/isaacs/init-package-json/issues"
},
"homepage": "https://github.com/isaacs/init-package-json",
- "_id": "init-package-json@1.1.3",
- "_shasum": "1d633c151a4909891afc8ee13cace8b336c0c9c2",
- "_from": "init-package-json@>=1.1.3 <1.2.0"
+ "_id": "init-package-json@1.2.0",
+ "_shasum": "b9f027514403b3b3f582c148592ab75214003348",
+ "_from": "init-package-json@>=1.2.0 <1.3.0",
+ "_npmVersion": "2.3.0",
+ "_nodeVersion": "0.10.35",
+ "_npmUser": {
+ "name": "othiym23",
+ "email": "ogd@aoaioxxysz.net"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ {
+ "name": "othiym23",
+ "email": "ogd@aoaioxxysz.net"
+ }
+ ],
+ "dist": {
+ "shasum": "b9f027514403b3b3f582c148592ab75214003348",
+ "tarball": "http://registry.npmjs.org/init-package-json/-/init-package-json-1.2.0.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.2.0.tgz"
}
test : 'echo "Error: no test specified" && exit 1'
},
keywords : [],
- author : "npmbot <n@p.m> (http://npm.im)",
+ author : "npmbot <n@p.m> (http://npm.im/)",
license : "WTFPL"
}
'-luuid.lib',
'-lodbc32.lib',
'-lDelayImp.lib',
- '-l"<(node_root_dir)/$(ConfigurationName)/iojs.lib"'
+ '-l"<(node_root_dir)/$(ConfigurationName)/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'
}
/**
- * Copies the iojs.lib file for the current target architecture into the
+ * Copies the node.lib file for the current target architecture into the
* current proper dev dir location.
*/
if (!win || !copyDevLib) return doBuild()
var buildDir = path.resolve(nodeDir, buildType)
- , archNodeLibPath = path.resolve(nodeDir, arch, 'iojs.lib')
- , buildNodeLibPath = path.resolve(buildDir, 'iojs.lib')
+ , archNodeLibPath = path.resolve(nodeDir, arch, 'node.lib')
+ , buildNodeLibPath = path.resolve(buildDir, 'node.lib')
mkdirp(buildDir, function (err, isNew) {
if (err) return callback(err)
log.verbose('"' + buildType + '" dir needed to be created?', isNew)
var rs = fs.createReadStream(archNodeLibPath)
, ws = fs.createWriteStream(buildNodeLibPath)
- log.verbose('copying "iojs.lib" for ' + arch, buildNodeLibPath)
+ log.verbose('copying "node.lib" for ' + arch, buildNodeLibPath)
rs.pipe(ws)
rs.on('error', callback)
ws.on('error', callback)
}
}
- var distUrl = gyp.opts['dist-url'] || gyp.opts.disturl || 'https://iojs.org/dist'
+ var distUrl = gyp.opts['dist-url'] || gyp.opts.disturl || 'http://nodejs.org/dist'
// Determine which node dev files version we are installing
// now download the node tarball
var tarPath = gyp.opts['tarball']
- var tarballUrl = tarPath ? tarPath : distUrl + '/v' + version + '/iojs-v' + version + '.tar.gz'
+ var tarballUrl = tarPath ? tarPath : distUrl + '/v' + version + '/node-v' + version + '.tar.gz'
, badDownload = false
, extractCount = 0
, gunzip = zlib.createGunzip()
var async = 0
if (win) {
- // need to download iojs.lib
+ // need to download node.lib
async++
downloadNodeLib(deref)
}
// check content shasums
for (var k in contentShasums) {
log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
- // TODO(piscisaureus) re-enable checksum verification when the correct files are in place.
- if (false || contentShasums[k] !== expectShasums[k]) {
+ if (contentShasums[k] !== expectShasums[k]) {
cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k]))
return
}
}
function downloadNodeLib (done) {
- log.verbose('on Windows; need to download `iojs.lib`...')
+ log.verbose('on Windows; need to download `node.lib`...')
var dir32 = path.resolve(devDir, 'ia32')
, dir64 = path.resolve(devDir, 'x64')
- , nodeLibPath32 = path.resolve(dir32, 'iojs.lib')
- , nodeLibPath64 = path.resolve(dir64, 'iojs.lib')
- , nodeLibUrl32 = distUrl + '/v' + version + '/win-x86/iojs.lib'
- , nodeLibUrl64 = distUrl + '/v' + version + '/win-x64/iojs.lib'
+ , nodeLibPath32 = path.resolve(dir32, 'node.lib')
+ , nodeLibPath64 = path.resolve(dir64, 'node.lib')
+ , nodeLibUrl32 = distUrl + '/v' + version + '/node.lib'
+ , nodeLibUrl64 = distUrl + '/v' + version + '/x64/node.lib'
- log.verbose('32-bit iojs.lib dir', dir32)
- log.verbose('64-bit iojs.lib dir', dir64)
- log.verbose('`iojs.lib` 32-bit url', nodeLibUrl32)
- log.verbose('`iojs.lib` 64-bit url', nodeLibUrl64)
+ log.verbose('32-bit node.lib dir', dir32)
+ log.verbose('64-bit node.lib dir', dir64)
+ log.verbose('`node.lib` 32-bit url', nodeLibUrl32)
+ log.verbose('`node.lib` 64-bit url', nodeLibUrl64)
var async = 2
mkdir(dir32, function (err) {
if (err) return done(err)
- log.verbose('streaming 32-bit iojs.lib to:', nodeLibPath32)
+ log.verbose('streaming 32-bit node.lib to:', nodeLibPath32)
var req = download(nodeLibUrl32)
if (!req) return
req.on('error', done)
req.on('response', function (res) {
if (res.statusCode !== 200) {
- done(new Error(res.statusCode + ' status code downloading 32-bit iojs.lib'))
+ done(new Error(res.statusCode + ' status code downloading 32-bit node.lib'))
return
}
getContentSha(res, function (_, checksum) {
- contentShasums['win-x86/iojs.lib'] = checksum
- log.verbose('content checksum', 'win-x86/iojs.lib', checksum)
+ contentShasums['node.lib'] = checksum
+ log.verbose('content checksum', 'node.lib', checksum)
})
var ws = fs.createWriteStream(nodeLibPath32)
})
mkdir(dir64, function (err) {
if (err) return done(err)
- log.verbose('streaming 64-bit iojs.lib to:', nodeLibPath64)
+ log.verbose('streaming 64-bit node.lib to:', nodeLibPath64)
var req = download(nodeLibUrl64)
if (!req) return
req.on('error', done)
req.on('response', function (res) {
if (res.statusCode !== 200) {
- done(new Error(res.statusCode + ' status code downloading 64-bit iojs.lib'))
+ done(new Error(res.statusCode + ' status code downloading 64-bit node.lib'))
return
}
getContentSha(res, function (_, checksum) {
- contentShasums['win-x64/iojs.lib'] = checksum
- log.verbose('content checksum', 'win-x64/iojs.lib', checksum)
+ contentShasums['x64/node.lib'] = checksum
+ log.verbose('content checksum', 'x64/node.lib', checksum)
})
var ws = fs.createWriteStream(nodeLibPath64)
## API
+### client.access(uri, params, cb)
+
+* `uri` {String} Registry URL for the package's access API endpoint.
+ Looks like `/-/package/<package name>/access`.
+* `params` {Object} Object containing per-request properties.
+ * `access` {String} New access level for the package. Can be either
+ `public` or `restricted`. Registry will raise an error if trying
+ to change the access level of an unscoped package.
+ * `auth` {Credentials}
+
+Set the access level for scoped packages. For now, there are only two
+access levels: "public" and "restricted".
+
### client.adduser(uri, params, cb)
* `uri` {String} Base registry URL.
Deprecate a version of a package in the registry.
+### client.distTags.fetch(uri, params, cb)
+
+* `uri` {String} Base URL for the registry.
+* `params` {Object} Object containing per-request properties.
+ * `package` {String} Name of the package.
+ * `auth` {Credentials}
+* `cb` {Function}
+
+Fetch all of the `dist-tags` for the named package.
+
+### client.distTags.add(uri, params, cb)
+
+* `uri` {String} Base URL for the registry.
+* `params` {Object} Object containing per-request properties.
+ * `package` {String} Name of the package.
+ * `distTag` {String} Name of the new `dist-tag`.
+ * `version` {String} Exact version to be mapped to the `dist-tag`.
+ * `auth` {Credentials}
+* `cb` {Function}
+
+Add (or replace) a single dist-tag onto the named package.
+
+### client.distTags.set(uri, params, cb)
+
+* `uri` {String} Base URL for the registry.
+* `params` {Object} Object containing per-request properties.
+ * `package` {String} Name of the package.
+ * `distTags` {Object} Object containing a map from tag names to package
+ versions.
+ * `auth` {Credentials}
+* `cb` {Function}
+
+Set all of the `dist-tags` for the named package at once, creating any
+`dist-tags` that do not already exit. Any `dist-tags` not included in the
+`distTags` map will be removed.
+
+### client.distTags.update(uri, params, cb)
+
+* `uri` {String} Base URL for the registry.
+* `params` {Object} Object containing per-request properties.
+ * `package` {String} Name of the package.
+ * `distTags` {Object} Object containing a map from tag names to package
+ versions.
+ * `auth` {Credentials}
+* `cb` {Function}
+
+Update the values of multiple `dist-tags`, creating any `dist-tags` that do
+not already exist. Any pre-existing `dist-tags` not included in the `distTags`
+map will be left alone.
+
+### client.distTags.rm(uri, params, cb)
+
+* `uri` {String} Base URL for the registry.
+* `params` {Object} Object containing per-request properties.
+ * `package` {String} Name of the package.
+ * `distTag` {String} Name of the new `dist-tag`.
+ * `auth` {Credentials}
+* `cb` {Function}
+
+Remove a single `dist-tag` from the named package.
+
### client.get(uri, params, cb)
* `uri` {String} The complete registry URI to fetch
* `uri` {String} The registry URI for the package to publish.
* `params` {Object} Object containing per-request properties.
* `metadata` {Object} Package metadata.
+ * `access` {String} Access for the package. Can be `public` or `restricted` (no default).
* `body` {Stream} Stream of the package body / tarball.
* `auth` {Credentials}
* `cb` {Function}
* `proxy.https` {URL} The URL to proxy HTTPS requests through. Defaults to be
the same as `proxy.http` if unset.
* `proxy.localAddress` {IP} The local address to use on multi-homed systems.
-* `ssl.ca` {String} Cerficate signing authority certificates to trust.
+* `ssl.ca` {String} Certificate signing authority certificates to trust.
* `ssl.certificate` {String} Client certificate (PEM encoded). Enable access
to servers that require client certificates.
* `ssl.key` {String} Private key (PEM encoded) for client certificate.
this.log = this.config.log || npmlog
delete this.config.log
+
+ var client = this
+ fs.readdirSync(join(__dirname, "lib")).forEach(function (f) {
+ var entry = join(__dirname, "lib", f)
+
+ // lib/group-name/operation.js -> client.groupName.operation
+ var stat = fs.statSync(entry)
+ if (stat.isDirectory()) {
+ var groupName = f.replace(/-([a-z])/, dashToCamel)
+ fs.readdirSync(entry).forEach(function (f) {
+ if (!f.match(/\.js$/)) return
+
+ if (!client[groupName]) {
+ // keep client.groupName.operation from stomping client.operation
+ client[groupName] = Object.create(client)
+ }
+ var name = f.replace(/\.js$/, "").replace(/-([a-z])/, dashToCamel)
+ client[groupName][name] = require(join(entry, f))
+ })
+ return
+ }
+
+ if (!f.match(/\.js$/)) return
+ var name = f.replace(/\.js$/, "").replace(/-([a-z])/, dashToCamel)
+ client[name] = require(entry)
+ })
}
-fs.readdirSync(join(__dirname, "lib")).forEach(function (f) {
- if (!f.match(/\.js$/)) return
- var name = f.replace(/\.js$/, "")
- .replace(/-([a-z])/, function (_, l) { return l.toUpperCase() })
- RegClient.prototype[name] = require(join(__dirname, "lib", f))
-})
+function dashToCamel (_, l) {
+ return l.toUpperCase()
+}
--- /dev/null
+module.exports = access
+
+var assert = require("assert")
+
+function access (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to access")
+ assert(params && typeof params === "object", "must pass params to access")
+ assert(typeof cb === "function", "muss pass callback to access")
+
+ assert(typeof params.level === "string", "must pass level to access")
+ assert(
+ ["public", "restricted"].indexOf(params.level) !== -1,
+ "access level must be either 'public' or 'restricted'"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to access"
+ )
+
+ var body = {
+ access : params.level
+ }
+
+ var options = {
+ method : "POST",
+ body : JSON.stringify(body),
+ auth : params.auth
+ }
+ this.request(uri, options, cb)
+}
--- /dev/null
+module.exports = add
+
+var assert = require("assert")
+var url = require("url")
+
+var npa = require("npm-package-arg")
+
+function add (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to distTags.add")
+ assert(
+ params && typeof params === "object",
+ "must pass params to distTags.add"
+ )
+ assert(typeof cb === "function", "muss pass callback to distTags.add")
+
+ assert(
+ typeof params.package === "string",
+ "must pass package name to distTags.add"
+ )
+ assert(
+ typeof params.distTag === "string",
+ "must pass package distTag name to distTags.add"
+ )
+ assert(
+ typeof params.version === "string",
+ "must pass version to be mapped to distTag to distTags.add"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to distTags.add"
+ )
+
+ var p = npa(params.package)
+ var package = p.scope ? params.package.replace("/", "%2f") : params.package
+ var rest = "-/package/"+package+"/dist-tags/"+params.distTag
+
+ var options = {
+ method : "PUT",
+ body : JSON.stringify(params.version),
+ auth : params.auth
+ }
+ this.request(url.resolve(uri, rest), options, cb)
+}
--- /dev/null
+module.exports = fetch
+
+var assert = require("assert")
+var url = require("url")
+
+var npa = require("npm-package-arg")
+
+function fetch (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to distTags.fetch")
+ assert(
+ params && typeof params === "object",
+ "must pass params to distTags.fetch"
+ )
+ assert(typeof cb === "function", "muss pass callback to distTags.fetch")
+
+ assert(
+ typeof params.package === "string",
+ "must pass package name to distTags.fetch"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to distTags.fetch"
+ )
+
+ var p = npa(params.package)
+ var package = p.scope ? params.package.replace("/", "%2f") : params.package
+ var rest = "-/package/"+package+"/dist-tags"
+
+ var options = {
+ method : "GET",
+ auth : params.auth
+ }
+ this.request(url.resolve(uri, rest), options, function (er, data) {
+ if (data && typeof data === "object") delete data._etag
+ cb(er, data)
+ })
+}
--- /dev/null
+module.exports = rm
+
+var assert = require("assert")
+var url = require("url")
+
+var npa = require("npm-package-arg")
+
+function rm (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to distTags.rm")
+ assert(
+ params && typeof params === "object",
+ "must pass params to distTags.rm"
+ )
+ assert(typeof cb === "function", "muss pass callback to distTags.rm")
+
+ assert(
+ typeof params.package === "string",
+ "must pass package name to distTags.rm"
+ )
+ assert(
+ typeof params.distTag === "string",
+ "must pass package distTag name to distTags.rm"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to distTags.rm"
+ )
+
+ var p = npa(params.package)
+ var package = p.scope ? params.package.replace("/", "%2f") : params.package
+ var rest = "-/package/"+package+"/dist-tags/"+params.distTag
+
+ var options = {
+ method : "DELETE",
+ auth : params.auth
+ }
+ this.request(url.resolve(uri, rest), options, cb)
+}
--- /dev/null
+module.exports = set
+
+var assert = require("assert")
+var url = require("url")
+
+var npa = require("npm-package-arg")
+
+function set (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to distTags.set")
+ assert(
+ params && typeof params === "object",
+ "must pass params to distTags.set"
+ )
+ assert(typeof cb === "function", "muss pass callback to distTags.set")
+
+ assert(
+ typeof params.package === "string",
+ "must pass package name to distTags.set"
+ )
+ assert(
+ params.distTags && typeof params.distTags === "object",
+ "must pass distTags map to distTags.set"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to distTags.set"
+ )
+
+ var p = npa(params.package)
+ var package = p.scope ? params.package.replace("/", "%2f") : params.package
+ var rest = "-/package/"+package+"/dist-tags"
+
+ var options = {
+ method : "PUT",
+ body : JSON.stringify(params.distTags),
+ auth : params.auth
+ }
+ this.request(url.resolve(uri, rest), options, cb)
+}
--- /dev/null
+module.exports = update
+
+var assert = require("assert")
+var url = require("url")
+
+var npa = require("npm-package-arg")
+
+function update (uri, params, cb) {
+ assert(typeof uri === "string", "must pass registry URI to distTags.update")
+ assert(
+ params && typeof params === "object",
+ "must pass params to distTags.update"
+ )
+ assert(typeof cb === "function", "muss pass callback to distTags.update")
+
+ assert(
+ typeof params.package === "string",
+ "must pass package name to distTags.update"
+ )
+ assert(
+ params.distTags && typeof params.distTags === "object",
+ "must pass distTags map to distTags.update"
+ )
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to distTags.update"
+ )
+
+ var p = npa(params.package)
+ var package = p.scope ? params.package.replace("/", "%2f") : params.package
+ var rest = "-/package/"+package+"/dist-tags"
+
+ var options = {
+ method : "POST",
+ body : JSON.stringify(params.distTags),
+ auth : params.auth
+ }
+ this.request(url.resolve(uri, rest), options, cb)
+}
assert(params && typeof params === "object", "must pass params to publish")
assert(typeof cb === "function", "must pass callback to publish")
+ var access = params.access
+ assert(access && typeof access === "string", "must pass access for package")
+ assert(
+ ["public", "restricted"].indexOf(access) !== -1,
+ "access level must be either 'public' or 'restricted'"
+ )
+
var auth = params.auth
assert(auth && typeof auth === "object", "must pass auth to publish")
if (!(auth.token ||
assert(body instanceof Stream, "package body passed to publish must be a stream")
var client = this
var sink = concat(function (tarbuffer) {
- putFirst.call(client, uri, metadata, tarbuffer, auth, cb)
+ putFirst.call(client, uri, metadata, tarbuffer, access, auth, cb)
})
sink.on("error", cb)
body.pipe(sink)
}
-function putFirst (registry, data, tarbuffer, auth, cb) {
+function putFirst (registry, data, tarbuffer, access, auth, cb) {
// optimistically try to PUT all in one single atomic thing.
// If 409, then GET and merge, try again.
// If other error, then fail.
{ _id : data.name
, name : data.name
, description : data.description
+ , access : access
, "dist-tags" : {}
, versions : {}
, readme: data.readme || ""
assert(typeof params.version === "string", "must pass version to tag")
assert(typeof params.tag === "string", "must pass tag name to tag")
- assert(params.auth && typeof params.auth === "object", "must pass auth to tag")
+ assert(
+ params.auth && typeof params.auth === "object",
+ "must pass auth to tag"
+ )
var options = {
method : "PUT",
--- /dev/null
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--- /dev/null
+# npm-package-arg
+
+Parse package name and specifier passed to commands like `npm install` or
+`npm cache add`. This just parses the text given-- it's worth noting that
+`npm` has further logic it applies by looking at your disk to figure out
+what ambiguous specifiers are. If you want that logic, please see
+[realize-package-specifier].
+
+[realize-package-specifier]: https://www.npmjs.org/package/realize-package-specifier
+
+Arguments look like: `foo@1.2`, `@bar/foo@1.2`, `foo@user/foo`, `http://x.com/foo.tgz`,
+`git+https://github.com/user/foo`, `bitbucket:user/foo`, `foo.tar.gz` or `bar`
+
+## EXAMPLES
+
+```javascript
+var assert = require("assert")
+var npa = require("npm-package-arg")
+
+// Pass in the descriptor, and it'll return an object
+var parsed = npa("@bar/foo@1.2")
+
+// Returns an object like:
+{
+ raw: '@bar/foo@1.2', // what was passed in
+ name: "foo", // the name of the package
+ scope: "@bar", // the private scope of the package, or null
+ type: "range", // the type of specifier this is
+ spec: ">=1.2.0 <1.3.0" // the expanded specifier
+ rawSpec: "1.2" // the specifier as passed in
+ }
+
+// Parsing urls pointing at hosted git services produces a variation:
+var parsed = npa("git+https://github.com/user/foo")
+
+// Returns an object like:
+{
+ raw: 'git+https://github.com/user/foo',
+ scope: null,
+ name: null,
+ rawSpec: 'git+https://github.com/user/foo',
+ spec: 'user/foo',
+ type: 'hosted',
+ hosted: {
+ type: 'github',
+ ssh: 'git@github.com:user/foo.git',
+ sshurl: 'git+ssh://git@github.com/user/foo.git',
+ https: 'https://github.com/user/foo.git',
+ directUrl: 'https://raw.githubusercontent.com/user/foo/master/package.json'
+ }
+}
+
+// Completely unreasonable invalid garbage throws an error
+// Make sure you wrap this in a try/catch if you have not
+// already sanitized the inputs!
+assert.throws(function() {
+ npa("this is not \0 a valid package name or url")
+})
+```
+
+## USING
+
+`var npa = require('npm-package-arg')`
+
+* var result = npa(*arg*)
+
+Parses *arg* and returns a result object detailing what *arg* is.
+
+*arg* -- a package descriptor, like: `foo@1.2`, or `foo@user/foo`, or
+`http://x.com/foo.tgz`, or `git+https://github.com/user/foo`
+
+## RESULT OBJECT
+
+The objects that are returned by npm-package-arg contain the following
+keys:
+
+* `name` - If known, the `name` field expected in the resulting pkg.
+* `type` - One of the following strings:
+ * `git` - A git repo
+ * `hosted` - A hosted project, from github, bitbucket or gitlab. Originally
+ either a full url pointing at one of these services or a shorthand like
+ `user/project` or `github:user/project` for github or `bitbucket:user/project`
+ for bitbucket.
+ * `tag` - A tagged version, like `"foo@latest"`
+ * `version` - A specific version number, like `"foo@1.2.3"`
+ * `range` - A version range, like `"foo@2.x"`
+ * `local` - A local file or folder path
+ * `remote` - An http url (presumably to a tgz)
+* `spec` - The "thing". URL, the range, git repo, etc.
+* `hosted` - If type=hosted this will be an object with the following keys:
+ * `type` - github, bitbucket or gitlab
+ * `ssh` - The ssh path for this git repo
+ * `sshUrl` - The ssh URL for this git repo
+ * `httpsUrl` - The HTTPS URL for this git repo
+ * `directUrl` - The URL for the package.json in this git repo
+* `raw` - The original un-modified string that was provided.
+* `rawSpec` - The part after the `name@...`, as it was originally
+ provided.
+* `scope` - If a name is something like `@org/module` then the `scope`
+ field will be set to `org`. If it doesn't have a scoped name, then
+ scope is `null`.
--- /dev/null
+*~
+.#
+node_modules
--- /dev/null
+language: node_js
+node_js:
+ - "0.11"
+ - "0.10"
+script: "npm test"
--- /dev/null
+# hosted-git-info
+
+This will let you identify and transform various git hosts URLs between
+protocols. It also can tell you what the URL is for the raw path for
+particular file for direct access without git.
+
+## Usage
+
+```javascript
+var hostedGitInfo = require("hosted-git-info")
+var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git")
+/* info looks like:
+{
+ type: "github",
+ domain: "github.com",
+ user: "npm",
+ project: "hosted-git-info"
+}
+*/
+```
+
+If the URL can't be matched with a git host, `null` will be returned. We
+can match git, ssh and https urls. Additionally, we can match ssh connect
+strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg,
+`github:npm/hosted-git-info`). Github specifically, is detected in the case
+of a third, unprefixed, form: `npm/hosted-git-info`.
+
+If it does match, the returned object has properties of:
+
+* info.type -- The short name of the service
+* info.domain -- The domain for git protocol use
+* info.user -- The name of the user/org on the git host
+* info.project -- The name of the project on the git host
+
+And methods of:
+
+* info.file(path)
+
+Given the path of a file relative to the repository, returns a URL for
+directly fetching it from the githost. If no comittish was set then
+`master` will be used as the default.
+
+For example `hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git#v1.0.0").file("package.json")`
+would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/package.json`
+
+* info.shortcut()
+
+eg, `github:npm/hosted-git-info`
+
+* info.browse()
+
+eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`
+
+* info.bugs()
+
+eg, `https://github.com/npm/hosted-git-info/issues`
+
+* info.docs()
+
+eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0#readme`
+
+* info.https()
+
+eg, `https://github.com/npm/hosted-git-info.git`
+
+* info.sshurl()
+
+eg, `git+ssh://git@github.com/npm/hosted-git-info.git`
+
+* info.ssh()
+
+eg, `git@github.com:npm/hosted-git-info.git`
+
+* info.path()
+
+eg, `npm/hosted-git-info`
+
+## Supported hosts
+
+Currently this supports Github, Bitbucket and Gitlab. Pull requests for
+additional hosts welcome.
--- /dev/null
+"use strict"
+var url = require("url")
+
+var GitHost = exports = module.exports = function (type, user, project, comittish) {
+ this.type = type
+ this.domain = gitHosts[type].domain
+ this.filetemplate = gitHosts[type].filetemplate
+ this.sshtemplate = gitHosts[type].sshtemplate
+ this.sshurltemplate = gitHosts[type].sshurltemplate
+ this.browsetemplate = gitHosts[type].browsetemplate
+ this.docstemplate = gitHosts[type].docstemplate
+ this.bugstemplate = gitHosts[type].bugstemplate
+ this.gittemplate = gitHosts[type].gittemplate
+ this.httpstemplate = gitHosts[type].httpstemplate
+ this.treepath = gitHosts[type].treepath
+ this.user = user
+ this.project = project
+ this.comittish = comittish
+}
+GitHost.prototype = {}
+
+exports.fromUrl = function (giturl) {
+ if (giturl == null || giturl == "") return
+ var parsed = parseGitUrl(maybeGitHubShorthand(giturl) ? "github:" + giturl : giturl)
+ var matches = Object.keys(gitHosts).map(function(V) {
+ var gitHost = gitHosts[V]
+ var comittish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
+ if (parsed.protocol == V + ":") {
+ return new GitHost(V,
+ decodeURIComponent(parsed.host), decodeURIComponent(parsed.path.replace(/^[/](.*?)(?:[.]git)?$/, "$1")), comittish)
+ }
+ if (parsed.host != gitHost.domain) return
+ if (! gitHost.protocols_re.test(parsed.protocol)) return
+ var matched = parsed.path.match(gitHost.pathmatch)
+ if (! matched) return
+ return new GitHost(
+ V,
+ matched[1]!=null && decodeURIComponent(matched[1]),
+ matched[2]!=null && decodeURIComponent(matched[2]),
+ comittish)
+ }).filter(function(V){ return V })
+ if (matches.length != 1) return
+ return matches[0]
+}
+
+function maybeGitHubShorthand(arg) {
+ // Note: This does not fully test the git ref format.
+ // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
+ //
+ // The only way to do this properly would be to shell out to
+ // git-check-ref-format, and as this is a fast sync function,
+ // we don't want to do that. Just let git fail if it turns
+ // out that the commit-ish is invalid.
+ // GH usernames cannot start with . or -
+ return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg)
+}
+
+var parseGitUrl = function (giturl) {
+ if (typeof giturl != "string") giturl = "" + giturl
+ var matched = giturl.match(/^([^@]+)@([^:]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
+ if (! matched) return url.parse(giturl)
+ return {
+ protocol: "git+ssh:",
+ slashes: true,
+ auth: matched[1],
+ host: matched[2],
+ port: null,
+ hostname: matched[2],
+ hash: matched[4],
+ search: null,
+ query: null,
+ pathname: "/" + matched[3],
+ path: "/" + matched[3],
+ href: "git+ssh://" + matched[1] + "@" + matched[2] + "/" + matched[3] + (matched[4]||"")
+ }
+}
+
+var gitHostDefaults = {
+ "sshtemplate": "git@{domain}:{user}/{project}.git{#comittish}",
+ "sshurltemplate": "git+ssh://git@{domain}/{user}/{project}.git{#comittish}",
+ "browsetemplate": "https://{domain}/{user}/{project}{/tree/comittish}",
+ "docstemplate": "https://{domain}/{user}/{project}{/tree/comittish}#readme",
+ "httpstemplate": "https://{domain}/{user}/{project}.git{#comittish}",
+ "filetemplate": "https://{domain}/{user}/{project}/raw/{comittish}/{path}"
+}
+var gitHosts = {
+ github: {
+ // First two are insecure and generally shouldn't be used any more, but
+ // they are still supported.
+ "protocols": [ "git", "http", "git+ssh", "git+https", "ssh", "https" ],
+ "domain": "github.com",
+ "pathmatch": /^[/]([^/]+)[/]([^/]+?)(?:[.]git)?$/,
+ "treepath": "tree",
+ "filetemplate": "https://raw.githubusercontent.com/{user}/{project}/{comittish}/{path}",
+ "bugstemplate": "https://{domain}/{user}/{project}/issues",
+ "gittemplate": "git://{domain}/{user}/{project}.git{#comittish}"
+ },
+ bitbucket: {
+ "protocols": [ "git+ssh", "git+https", "ssh", "https" ],
+ "domain": "bitbucket.org",
+ "pathmatch": /^[/]([^/]+)[/]([^/]+?)(?:[.]git)?$/,
+ "treepath": "src"
+ },
+ gitlab: {
+ "protocols": [ "git+ssh", "git+https", "ssh", "https" ],
+ "domain": "gitlab.com",
+ "pathmatch": /^[/]([^/]+)[/]([^/]+?)(?:[.]git)?$/,
+ "treepath": "tree",
+ "docstemplate": "https://{domain}/{user}/{project}{/tree/comittish}#README",
+ "bugstemplate": "https://{domain}/{user}/{project}/issues"
+ },
+ gist: {
+ "protocols": [ "git", "git+ssh", "git+https", "ssh", "https" ],
+ "domain": "gist.github.com",
+ "pathmatch": /^[/](?:([^/]+)[/])?([a-z0-9]+)(?:[.]git)?$/,
+ "filetemplate": "https://gist.githubusercontent.com/{user}/{project}/raw{/comittish}/{path}",
+ "bugstemplate": "https://{domain}/{project}",
+ "gittemplate": "git://{domain}/{project}.git{#comittish}",
+ "sshtemplate": "git@{domain}:/{project}.git{#comittish}",
+ "sshurltemplate": "git+ssh://git@{domain}/{project}.git{#comittish}",
+ "browsetemplate": "https://{domain}/{project}{/comittish}",
+ "docstemplate": "https://{domain}/{project}{/comittish}",
+ "httpstemplate": "https://{domain}/{project}.git{#comittish}",
+ },
+}
+
+Object.keys(gitHosts).forEach(function(host) {
+ gitHosts[host].protocols_re = RegExp("^(" +
+ gitHosts[host].protocols.map(function(P){
+ return P.replace(/([\\+*{}()\[\]$^|])/g, "\\$1")
+ }).join("|") + "):$")
+})
+
+GitHost.prototype.shortcut = function () {
+ return this.type + ":" + this.path()
+}
+
+GitHost.prototype.hash = function () {
+ return this.comittish ? "#" + this.comittish : ""
+}
+
+GitHost.prototype.path = function () {
+ return this.user + "/" + this.project + this.hash()
+}
+
+GitHost.prototype._fill = function (template, vars) {
+ if (!template) throw new Error("Tried to fill without template")
+ if (!vars) vars = {}
+ var self = this
+ Object.keys(this).forEach(function(K){ if (self[K]!=null && vars[K]==null) vars[K] = self[K] })
+ var rawComittish = vars.comittish
+ Object.keys(vars).forEach(function(K){ (K[0]!='#') && (vars[K] = encodeURIComponent(vars[K])) })
+ vars["#comittish"] = rawComittish ? "#" + rawComittish : ""
+ vars["/tree/comittish"] = vars.comittish ? "/"+vars.treepath+"/" + vars.comittish : "",
+ vars["/comittish"] = vars.comittish ? "/" + vars.comittish : ""
+ vars.comittish = vars.comittish || "master"
+ var res = template
+ Object.keys(vars).forEach(function(K){
+ res = res.replace(new RegExp("[{]" + K + "[}]", "g"), vars[K])
+ })
+ return res
+}
+
+GitHost.prototype.ssh = function () {
+ var sshtemplate = this.sshtemplate || gitHostDefaults.sshtemplate
+ return this._fill(sshtemplate)
+}
+
+GitHost.prototype.sshurl = function () {
+ var sshurltemplate = this.sshurltemplate || gitHostDefaults.sshurltemplate
+ return this._fill(sshurltemplate)
+}
+
+GitHost.prototype.browse = function () {
+ var browsetemplate = this.browsetemplate || gitHostDefaults.browsetemplate
+ return this._fill(browsetemplate)
+}
+
+GitHost.prototype.docs = function () {
+ var docstemplate = this.docstemplate || gitHostDefaults.docstemplate
+ return this._fill(docstemplate)
+}
+
+GitHost.prototype.bugs = function() {
+ if (! this.bugstemplate) return
+ return this._fill(this.bugstemplate)
+}
+
+GitHost.prototype.https = function () {
+ var httpstemplate = this.httpstemplate || gitHostDefaults.httpstemplate
+ return this._fill(httpstemplate)
+}
+
+GitHost.prototype.git = function () {
+ if (! this.gittemplate) return
+ return this._fill(this.gittemplate)
+}
+
+GitHost.prototype.file = function (P) {
+ var filetemplate = this.filetemplate || gitHostDefaults.filetemplate
+ return this._fill(filetemplate, {
+ path: P.replace(/^[/]+/g, "")
+ })
+}
+
+GitHost.prototype.toString = function () {
+ return this[this.default||"sshurl"]()
+}
--- /dev/null
+{
+ "name": "hosted-git-info",
+ "version": "1.5.3",
+ "description": "Provides metadata and conversions from repository urls for Github, Bitbucket and Gitlab",
+ "main": "index.js",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/npm/hosted-git-info.git"
+ },
+ "keywords": [
+ "git",
+ "github",
+ "bitbucket",
+ "gitlab"
+ ],
+ "author": {
+ "name": "Rebecca Turner",
+ "email": "me@re-becca.org",
+ "url": "http://re-becca.org"
+ },
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/npm/hosted-git-info/issues"
+ },
+ "homepage": "https://github.com/npm/hosted-git-info",
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "devDependencies": {
+ "tap": "^0.4.13"
+ },
+ "gitHead": "153325f997813ebf8a7ae07b322b4fa89aa25f7d",
+ "_id": "hosted-git-info@1.5.3",
+ "_shasum": "1f46e25e9c0e207852fb7a4b94422ed5f09a03f5",
+ "_from": "hosted-git-info@>=1.4.0 <2.0.0",
+ "_npmVersion": "2.4.0",
+ "_nodeVersion": "0.10.33",
+ "_npmUser": {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ },
+ "maintainers": [
+ {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ }
+ ],
+ "dist": {
+ "shasum": "1f46e25e9c0e207852fb7a4b94422ed5f09a03f5",
+ "tarball": "http://registry.npmjs.org/hosted-git-info/-/hosted-git-info-1.5.3.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-1.5.3.tgz",
+ "readme": "ERROR: No README data found!"
+}
--- /dev/null
+"use strict"
+var HostedGit = require("../index")
+var test = require("tap").test
+
+test("basic", function (t) {
+ t.is(HostedGit.fromUrl("https://google.com"), undefined, "null on failure")
+
+ t.end()
+})
--- /dev/null
+"use strict"
+var HostedGit = require("../index")
+var test = require("tap").test
+
+test("fromUrl(bitbucket url)", function (t) {
+ function verify(host, label, branch) {
+ var hostinfo = HostedGit.fromUrl(host)
+ var hash = branch ? "#" + branch : ""
+ t.ok(hostinfo, label)
+ if (! hostinfo) return
+ t.is( hostinfo.https(), "https://bitbucket.org/111/222.git" + hash, label + " -> https" )
+ t.is( hostinfo.browse(), "https://bitbucket.org/111/222" + (branch ? "/src/" + branch : ""), label + " -> browse" )
+ t.is( hostinfo.docs(), "https://bitbucket.org/111/222" + (branch ? "/src/" + branch : "") + "#readme", label + " -> docs" )
+ t.is( hostinfo.ssh(), "git@bitbucket.org:111/222.git" + hash, label + " -> ssh" )
+ t.is( hostinfo.sshurl(), "git+ssh://git@bitbucket.org/111/222.git" + hash, label + " -> sshurl" )
+ t.is( (""+hostinfo), "git+ssh://git@bitbucket.org/111/222.git" + hash, label + " -> stringify" )
+ t.is( hostinfo.file("C"), "https://bitbucket.org/111/222/raw/"+(branch||"master")+"/C", label + " -> file" )
+ }
+
+ require('./lib/standard-tests')(verify, "bitbucket.org", "bitbucket")
+
+ t.end()
+})
--- /dev/null
+"use strict"
+var HostedGit = require("../index")
+var test = require("tap").test
+
+
+test("fromUrl(gist url)", function (t) {
+ function verify(host, label, branch) {
+ var hostinfo = HostedGit.fromUrl(host)
+ var hash = branch ? "#" + branch : ""
+ t.ok(hostinfo, label)
+ if (! hostinfo) return
+ t.is( hostinfo.https(), "https://gist.github.com/222.git" + hash, label + " -> https" )
+ t.is( hostinfo.git(), "git://gist.github.com/222.git" + hash, label + " -> git" )
+ t.is( hostinfo.browse(), "https://gist.github.com/222" + (branch ? "/" + branch : ""), label + " -> browse" )
+ t.is( hostinfo.bugs(), "https://gist.github.com/222", label + " -> bugs" )
+ t.is( hostinfo.docs(), "https://gist.github.com/222" + (branch ? "/" + branch : ""), label + " -> docs" )
+ t.is( hostinfo.ssh(), "git@gist.github.com:/222.git" + hash, label + " -> ssh" )
+ t.is( hostinfo.sshurl(), "git+ssh://git@gist.github.com/222.git" + hash, label + " -> sshurl" )
+ t.is( (""+hostinfo), "git+ssh://git@gist.github.com/222.git" + hash, label + " -> stringify" )
+ if (hostinfo.user) {
+ t.is( hostinfo.file("C"), "https://gist.githubusercontent.com/111/222/raw/"+(branch?branch+"/":"")+"C", label + " -> file" )
+ }
+ }
+
+ verify("git@gist.github.com:222.git", "git@")
+ var hostinfo = HostedGit.fromUrl("git@gist.github.com:/ef860c7z5e0de3179341.git")
+ if (t.ok(hostinfo, "git@hex")) {
+ t.is( hostinfo.https(), "https://gist.github.com/ef860c7z5e0de3179341.git", "git@hex -> https" )
+ }
+ verify("git@gist.github.com:/222.git", "git@/")
+ verify("git://gist.github.com/222", "git")
+ verify("git://gist.github.com/222.git", "git.git")
+ verify("git://gist.github.com/222#branch", "git#branch", "branch")
+ verify("git://gist.github.com/222.git#branch", "git.git#branch", "branch")
+
+ require('./lib/standard-tests')(verify, "gist.github.com", "gist")
+
+ t.end()
+})
--- /dev/null
+"use strict"
+var HostedGit = require("../index")
+var test = require("tap").test
+
+
+test("fromUrl(github url)", function (t) {
+ function verify(host, label, branch) {
+ var hostinfo = HostedGit.fromUrl(host)
+ var hash = branch ? "#" + branch : ""
+ t.ok(hostinfo, label)
+ if (! hostinfo) return
+ t.is( hostinfo.https(), "https://github.com/111/222.git" + hash, label + " -> https" )
+ t.is( hostinfo.git(), "git://github.com/111/222.git" + hash, label + " -> git" )
+ t.is( hostinfo.browse(), "https://github.com/111/222" + (branch ? "/tree/" + branch : ""), label + " -> browse" )
+ t.is( hostinfo.bugs(), "https://github.com/111/222/issues", label + " -> bugs" )
+ t.is( hostinfo.docs(), "https://github.com/111/222" + (branch ? "/tree/" + branch : "") + "#readme", label + " -> docs" )
+ t.is( hostinfo.ssh(), "git@github.com:111/222.git" + hash, label + " -> ssh" )
+ t.is( hostinfo.sshurl(), "git+ssh://git@github.com/111/222.git" + hash, label + " -> sshurl" )
+ t.is( (""+hostinfo), "git+ssh://git@github.com/111/222.git" + hash, label + " -> stringify" )
+ t.is( hostinfo.file("C"), "https://raw.githubusercontent.com/111/222/"+(branch||"master")+"/C", label + " -> file" )
+ }
+
+ // github shorturls
+ verify("111/222", "github-short")
+ verify("111/222#branch", "github-short#branch", "branch")
+
+ // insecure protocols
+ verify("git://github.com/111/222", "git")
+ verify("git://github.com/111/222.git", "git.git")
+ verify("git://github.com/111/222#branch", "git#branch", "branch")
+ verify("git://github.com/111/222.git#branch", "git.git#branch", "branch")
+
+ verify("http://github.com/111/222", "http")
+ verify("http://github.com/111/222.git", "http.git")
+ verify("http://github.com/111/222#branch", "http#branch", "branch")
+ verify("http://github.com/111/222.git#branch", "http.git#branch", "branch")
+
+ require('./lib/standard-tests')(verify, "github.com", "github")
+
+ t.end()
+})
--- /dev/null
+"use strict"
+var HostedGit = require("../index")
+var test = require("tap").test
+
+
+test("fromUrl(gitlab url)", function (t) {
+ function verify(host, label, branch) {
+ var hostinfo = HostedGit.fromUrl(host)
+ var hash = branch ? "#" + branch : ""
+ t.ok(hostinfo, label)
+ if (! hostinfo) return
+ t.is( hostinfo.https(), "https://gitlab.com/111/222.git" + hash, label + " -> https" )
+ t.is( hostinfo.browse(), "https://gitlab.com/111/222" + (branch ? "/tree/" + branch : ""), label + " -> browse" )
+ t.is( hostinfo.docs(), "https://gitlab.com/111/222" + (branch ? "/tree/" + branch : "") + "#README", label + " -> docs" )
+ t.is( hostinfo.ssh(), "git@gitlab.com:111/222.git" + hash, label + " -> ssh" )
+ t.is( hostinfo.sshurl(), "git+ssh://git@gitlab.com/111/222.git" + hash, label + " -> sshurl" )
+ t.is( (""+hostinfo), "git+ssh://git@gitlab.com/111/222.git" + hash, label + " -> stringify" )
+ t.is( hostinfo.file("C"), "https://gitlab.com/111/222/raw/"+(branch||"master")+"/C", label + " -> file" )
+ }
+
+ require('./lib/standard-tests')(verify, "gitlab.com", "gitlab")
+
+ t.end()
+})
--- /dev/null
+"use strict"
+module.exports = function (verify, domain, shortname) {
+ verify("https://" + domain + "/111/222", "https")
+ verify("https://" + domain + "/111/222.git", "https.git")
+ verify("https://" + domain + "/111/222#branch", "https#branch", "branch")
+ verify("https://" + domain + "/111/222.git#branch", "https.git#branch", "branch")
+
+ verify("git+https://" + domain + "/111/222", "git+https")
+ verify("git+https://" + domain + "/111/222.git", "git+https.git")
+ verify("git+https://" + domain + "/111/222#branch", "git+https#branch", "branch")
+ verify("git+https://" + domain + "/111/222.git#branch", "git+https.git#branch", "branch")
+
+ verify("git@" + domain + ":111/222", "ssh")
+ verify("git@" + domain + ":111/222.git", "ssh.git")
+ verify("git@" + domain + ":111/222#branch", "ssh", "branch")
+ verify("git@" + domain + ":111/222.git#branch", "ssh.git", "branch")
+
+
+ verify("git+ssh://git@" + domain + "/111/222", "ssh url")
+ verify("git+ssh://git@" + domain + "/111/222.git", "ssh url.git")
+ verify("git+ssh://git@" + domain + "/111/222#branch", "ssh url#branch", "branch")
+ verify("git+ssh://git@" + domain + "/111/222.git#branch", "ssh url.git#branch", "branch")
+
+ verify(shortname + ":111/222", "shortcut")
+ verify(shortname + ":111/222.git", "shortcut.git")
+ verify(shortname + ":111/222#branch", "shortcut#branch", "branch")
+ verify(shortname + ":111/222.git#branch", "shortcut.git#branch", "branch")
+}
--- /dev/null
+var url = require("url")
+var assert = require("assert")
+var util = require("util")
+var semver = require("semver")
+var path = require("path")
+var HostedGit = require("hosted-git-info")
+
+module.exports = npa
+
+var isWindows = process.platform === "win32" || global.FAKE_WINDOWS
+var slashRe = isWindows ? /\\|[/]/ : /[/]/
+
+var parseName = /^(?:@([^/]+?)[/])?([^/]+?)$/
+var nameAt = /^(@([^/]+?)[/])?([^/]+?)@/
+var debug = util.debuglog ? util.debuglog("npa")
+ : /\bnpa\b/i.test(process.env.NODE_DEBUG || "")
+ ? function () {
+ console.error("NPA: " + util.format.apply(util, arguments).split("\n").join("\nNPA: "))
+ } : function () {}
+
+function validName (name) {
+ if (!name) {
+ debug("not a name %j", name)
+ return false
+ }
+ var n = name.trim()
+ if (!n || n.charAt(0) === "."
+ || !n.match(/^[a-zA-Z0-9]/)
+ || n.match(/[/()&?#|<>@:%\s\\*'"!~`]/)
+ || n.toLowerCase() === "node_modules"
+ || n !== encodeURIComponent(n)
+ || n.toLowerCase() === "favicon.ico") {
+ debug("not a valid name %j", name)
+ return false
+ }
+ return n
+}
+
+function npa (arg) {
+ assert.equal(typeof arg, "string")
+ arg = arg.trim()
+
+ var res = new Result
+ res.raw = arg
+ res.scope = null
+
+ // See if it's something like foo@...
+ var nameparse = arg.match(nameAt)
+ debug("nameparse", nameparse)
+ if (nameparse && validName(nameparse[3]) &&
+ (!nameparse[2] || validName(nameparse[2]))) {
+ res.name = (nameparse[1] || "") + nameparse[3]
+ if (nameparse[2])
+ res.scope = "@" + nameparse[2]
+ arg = arg.substr(nameparse[0].length)
+ } else {
+ res.name = null
+ }
+
+ res.rawSpec = arg
+ res.spec = arg
+
+ var urlparse = url.parse(arg)
+ debug("urlparse", urlparse)
+
+ // windows paths look like urls
+ // don't be fooled!
+ if (isWindows && urlparse && urlparse.protocol &&
+ urlparse.protocol.match(/^[a-zA-Z]:$/)) {
+ debug("windows url-ish local path", urlparse)
+ urlparse = {}
+ }
+
+ if (urlparse.protocol || HostedGit.fromUrl(arg)) {
+ return parseUrl(res, arg, urlparse)
+ }
+
+ // at this point, it's not a url, and not hosted
+ // If it's a valid name, and doesn't already have a name, then assume
+ // $name@"" range
+ //
+ // if it's got / chars in it, then assume that it's local.
+
+ if (res.name) {
+ var version = semver.valid(arg, true)
+ var range = semver.validRange(arg, true)
+ // foo@...
+ if (version) {
+ res.spec = version
+ res.type = "version"
+ } else if (range) {
+ res.spec = range
+ res.type = "range"
+ } else if (slashRe.test(arg)) {
+ parseLocal(res, arg)
+ } else {
+ res.type = "tag"
+ res.spec = arg
+ }
+ } else {
+ var p = arg.match(parseName)
+ if (p && validName(p[2]) &&
+ (!p[1] || validName(p[1]))) {
+ res.type = "range"
+ res.spec = "*"
+ res.rawSpec = ""
+ res.name = arg
+ if (p[1])
+ res.scope = "@" + p[1]
+ } else {
+ parseLocal(res, arg)
+ }
+ }
+
+ return res
+}
+
+function parseLocal (res, arg) {
+ // turns out nearly every character is allowed in fs paths
+ if (/\0/.test(arg)) {
+ throw new Error("Invalid Path: " + JSON.stringify(arg))
+ }
+ res.type = "local"
+ res.spec = path.resolve(arg)
+}
+
+function parseUrl (res, arg, urlparse) {
+ var gitHost = HostedGit.fromUrl(arg)
+ if (gitHost) {
+ res.type = "hosted"
+ res.spec = gitHost.toString(),
+ res.hosted = {
+ type: gitHost.type,
+ ssh: gitHost.ssh(),
+ sshUrl: gitHost.sshurl(),
+ httpsUrl: gitHost.https(),
+ directUrl: gitHost.file("package.json")
+ }
+ return res
+ }
+ // check the protocol, and then see if it's git or not
+ switch (urlparse.protocol) {
+ case "git:":
+ case "git+http:":
+ case "git+https:":
+ case "git+rsync:":
+ case "git+ftp:":
+ case "git+ssh:":
+ case "git+file:":
+ res.type = "git"
+ res.spec = arg.replace(/^git[+]/, "")
+ break
+
+ case "http:":
+ case "https:":
+ res.type = "remote"
+ res.spec = arg
+ break
+
+ case "file:":
+ res.type = "local"
+ res.spec = urlparse.pathname
+ break
+
+ default:
+ throw new Error("Unsupported URL Type: " + arg)
+ break
+ }
+
+ return res
+}
+
+
+function Result () {
+ if (!(this instanceof Result)) return new Result
+}
+Result.prototype.name = null
+Result.prototype.type = null
+Result.prototype.spec = null
+Result.prototype.raw = null
+Result.prototype.hosted = null
--- /dev/null
+{
+ "name": "npm-package-arg",
+ "version": "3.0.0",
+ "description": "Parse the things that can be arguments to `npm install`",
+ "main": "npa.js",
+ "directories": {
+ "test": "test"
+ },
+ "dependencies": {
+ "hosted-git-info": "^1.4.0",
+ "semver": "4"
+ },
+ "devDependencies": {
+ "tap": "^0.4.9"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/npm/npm-package-arg"
+ },
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "http://blog.izs.me/"
+ },
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/npm/npm-package-arg/issues"
+ },
+ "homepage": "https://github.com/npm/npm-package-arg",
+ "gitHead": "263fd43295ac8f6eca046be108782cfbf9a78bfe",
+ "_id": "npm-package-arg@3.0.0",
+ "_shasum": "84e91836fa2e4e35ae26dc984440b1e5b5aee1ee",
+ "_from": "npm-package-arg@>=3.0.0 <4.0.0",
+ "_npmVersion": "1.4.28",
+ "_npmUser": {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ {
+ "name": "othiym23",
+ "email": "ogd@aoaioxxysz.net"
+ },
+ {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ }
+ ],
+ "dist": {
+ "shasum": "84e91836fa2e4e35ae26dc984440b1e5b5aee1ee",
+ "tarball": "http://registry.npmjs.org/npm-package-arg/-/npm-package-arg-3.0.0.tgz"
+ },
+ "_resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-3.0.0.tgz",
+ "readme": "ERROR: No README data found!"
+}
--- /dev/null
+var npa = require("../npa.js")
+var path = require("path")
+
+require("tap").test("basic", function (t) {
+ t.setMaxListeners(999)
+
+ var tests = {
+ "foo@1.2": {
+ name: "foo",
+ type: "range",
+ spec: ">=1.2.0 <1.3.0",
+ raw: "foo@1.2",
+ rawSpec: "1.2"
+ },
+
+ "@foo/bar": {
+ raw: "@foo/bar",
+ name: "@foo/bar",
+ scope: "@foo",
+ rawSpec: "",
+ spec: "*",
+ type: "range"
+ },
+
+ "@foo/bar@": {
+ raw: "@foo/bar@",
+ name: "@foo/bar",
+ scope: "@foo",
+ rawSpec: "",
+ spec: "*",
+ type: "range"
+ },
+
+ "@foo/bar@baz": {
+ raw: "@foo/bar@baz",
+ name: "@foo/bar",
+ scope: "@foo",
+ rawSpec: "baz",
+ spec: "baz",
+ type: "tag"
+ },
+
+ "@f fo o al/ a d s ;f ": {
+ raw: "@f fo o al/ a d s ;f",
+ name: null,
+ rawSpec: "@f fo o al/ a d s ;f",
+ spec: path.resolve("@f fo o al/ a d s ;f"),
+ type: "local"
+ },
+
+ "foo@1.2.3": {
+ name: "foo",
+ type: "version",
+ spec: "1.2.3",
+ raw: "foo@1.2.3"
+ },
+
+ "foo@=v1.2.3": {
+ name: "foo",
+ type: "version",
+ spec: "1.2.3",
+ raw: "foo@=v1.2.3",
+ rawSpec: "=v1.2.3"
+ },
+
+ "git+ssh://git@notgithub.com/user/foo#1.2.3": {
+ name: null,
+ type: "git",
+ spec: "ssh://git@notgithub.com/user/foo#1.2.3",
+ raw: "git+ssh://git@notgithub.com/user/foo#1.2.3"
+ },
+
+ "git+file://path/to/repo#1.2.3": {
+ name: null,
+ type: "git",
+ spec: "file://path/to/repo#1.2.3",
+ raw: "git+file://path/to/repo#1.2.3"
+ },
+
+ "git://notgithub.com/user/foo": {
+ name: null,
+ type: "git",
+ spec: "git://notgithub.com/user/foo",
+ raw: "git://notgithub.com/user/foo"
+ },
+
+ "@foo/bar@git+ssh://notgithub.com/user/foo": {
+ name: "@foo/bar",
+ scope: "@foo",
+ spec: "ssh://notgithub.com/user/foo",
+ rawSpec: "git+ssh://notgithub.com/user/foo",
+ raw: "@foo/bar@git+ssh://notgithub.com/user/foo"
+ },
+
+ "/path/to/foo": {
+ name: null,
+ type: "local",
+ spec: "/path/to/foo",
+ raw: "/path/to/foo"
+ },
+
+ "file:path/to/foo": {
+ name: null,
+ type: "local",
+ spec: "path/to/foo",
+ raw: "file:path/to/foo"
+ },
+
+ "file:~/path/to/foo": {
+ name: null,
+ type: "local",
+ spec: "~/path/to/foo",
+ raw: "file:~/path/to/foo"
+ },
+
+ "file:../path/to/foo": {
+ name: null,
+ type: "local",
+ spec: "../path/to/foo",
+ raw: "file:../path/to/foo"
+ },
+
+ "file:///path/to/foo": {
+ name: null,
+ type: "local",
+ spec: "/path/to/foo",
+ raw: "file:///path/to/foo"
+ },
+
+ "https://server.com/foo.tgz": {
+ name: null,
+ type: "remote",
+ spec: "https://server.com/foo.tgz",
+ raw: "https://server.com/foo.tgz"
+ },
+
+ "foo@latest": {
+ name: "foo",
+ type: "tag",
+ spec: "latest",
+ raw: "foo@latest"
+ },
+
+ "foo": {
+ name: "foo",
+ type: "range",
+ spec: "*",
+ raw: "foo"
+ }
+ }
+
+ Object.keys(tests).forEach(function (arg) {
+ var res = npa(arg)
+ t.type(res, "Result", arg + " is result")
+ t.has(res, tests[arg], arg + " matches expectations")
+ })
+
+ // Completely unreasonable invalid garbage throws an error
+ t.throws(function() {
+ npa("this is not a \0 valid package name or url")
+ })
+
+ t.throws(function() {
+ npa("gopher://yea right")
+ }, "Unsupported URL Type: gopher://yea right")
+
+ t.end()
+})
--- /dev/null
+var npa = require("../npa.js")
+var path = require("path")
+
+require("tap").test("basic", function (t) {
+ t.setMaxListeners(999)
+
+ var tests = {
+ "bitbucket:user/foo-js": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo-js.git",
+ raw: "bitbucket:user/foo-js"
+ },
+
+ "bitbucket:user/foo-js#bar/baz": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo-js.git#bar/baz",
+ raw: "bitbucket:user/foo-js#bar/baz"
+ },
+
+ "bitbucket:user..blerg--/..foo-js# . . . . . some . tags / / /": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user..blerg--/..foo-js.git# . . . . . some . tags / / /",
+ raw: "bitbucket:user..blerg--/..foo-js# . . . . . some . tags / / /"
+ },
+
+ "bitbucket:user/foo-js#bar/baz/bin": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo-js.git#bar/baz/bin",
+ raw: "bitbucket:user/foo-js#bar/baz/bin"
+ },
+
+ "foo@bitbucket:user/foo-js": {
+ name: "foo",
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo-js.git",
+ raw: "foo@bitbucket:user/foo-js"
+ },
+
+ "git+ssh://git@bitbucket.org/user/foo#1.2.3": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo.git#1.2.3",
+ raw: "git+ssh://git@bitbucket.org/user/foo#1.2.3"
+ },
+
+ "https://bitbucket.org/user/foo.git": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo.git",
+ raw: "https://bitbucket.org/user/foo.git"
+ },
+
+ "@foo/bar@git+ssh://bitbucket.org/user/foo": {
+ name: "@foo/bar",
+ scope: "@foo",
+ type: "hosted",
+ hosted: { type: "bitbucket" },
+ spec: "git+ssh://git@bitbucket.org/user/foo.git",
+ rawSpec: "git+ssh://bitbucket.org/user/foo",
+ raw: "@foo/bar@git+ssh://bitbucket.org/user/foo"
+ }
+ }
+
+ Object.keys(tests).forEach(function (arg) {
+ var res = npa(arg)
+ t.type(res, "Result", arg + " is a result")
+ t.has(res, tests[arg], arg + " matches expectations")
+ })
+
+ t.end()
+})
--- /dev/null
+var npa = require("../npa.js")
+var path = require("path")
+
+require("tap").test("basic", function (t) {
+ t.setMaxListeners(999)
+
+ var tests = {
+ "user/foo-js": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo-js.git",
+ raw: "user/foo-js"
+ },
+
+ "user/foo-js#bar/baz": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo-js.git#bar/baz",
+ raw: "user/foo-js#bar/baz"
+ },
+
+ "user..blerg--/..foo-js# . . . . . some . tags / / /": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user..blerg--/..foo-js.git# . . . . . some . tags / / /",
+ raw: "user..blerg--/..foo-js# . . . . . some . tags / / /"
+ },
+
+ "user/foo-js#bar/baz/bin": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo-js.git#bar/baz/bin",
+ raw: "user/foo-js#bar/baz/bin"
+ },
+
+ "foo@user/foo-js": {
+ name: "foo",
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo-js.git",
+ raw: "foo@user/foo-js"
+ },
+
+ "github:user/foo-js": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo-js.git",
+ raw: "github:user/foo-js"
+ },
+
+ "git+ssh://git@github.com/user/foo#1.2.3": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo.git#1.2.3",
+ raw: "git+ssh://git@github.com/user/foo#1.2.3"
+ },
+
+ "git://github.com/user/foo": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo.git",
+ raw: "git://github.com/user/foo"
+ },
+
+ "https://github.com/user/foo.git": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo.git",
+ raw: "https://github.com/user/foo.git"
+ },
+
+ "@foo/bar@git+ssh://github.com/user/foo": {
+ name: "@foo/bar",
+ scope: "@foo",
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/user/foo.git",
+ rawSpec: "git+ssh://github.com/user/foo",
+ raw: "@foo/bar@git+ssh://github.com/user/foo"
+ },
+
+ "foo@bar/foo": {
+ name: "foo",
+ type: "hosted",
+ hosted: { type: "github" },
+ spec: "git+ssh://git@github.com/bar/foo.git",
+ raw: "foo@bar/foo"
+ }
+ }
+
+ Object.keys(tests).forEach(function (arg) {
+ var res = npa(arg)
+ t.type(res, "Result", arg + " is a result")
+ t.has(res, tests[arg], arg + " matches expectations")
+ })
+
+ t.end()
+})
--- /dev/null
+var npa = require("../npa.js")
+var path = require("path")
+
+require("tap").test("basic", function (t) {
+ t.setMaxListeners(999)
+
+ var tests = {
+ "gitlab:user/foo-js": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo-js.git",
+ raw: "gitlab:user/foo-js"
+ },
+
+ "gitlab:user/foo-js#bar/baz": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo-js.git#bar/baz",
+ raw: "gitlab:user/foo-js#bar/baz"
+ },
+
+ "gitlab:user..blerg--/..foo-js# . . . . . some . tags / / /": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user..blerg--/..foo-js.git# . . . . . some . tags / / /",
+ raw: "gitlab:user..blerg--/..foo-js# . . . . . some . tags / / /"
+ },
+
+ "gitlab:user/foo-js#bar/baz/bin": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo-js.git#bar/baz/bin",
+ raw: "gitlab:user/foo-js#bar/baz/bin"
+ },
+
+ "foo@gitlab:user/foo-js": {
+ name: "foo",
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo-js.git",
+ raw: "foo@gitlab:user/foo-js"
+ },
+
+ "git+ssh://git@gitlab.com/user/foo#1.2.3": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo.git#1.2.3",
+ raw: "git+ssh://git@gitlab.com/user/foo#1.2.3"
+ },
+
+ "https://gitlab.com/user/foo.git": {
+ name: null,
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo.git",
+ raw: "https://gitlab.com/user/foo.git"
+ },
+
+ "@foo/bar@git+ssh://gitlab.com/user/foo": {
+ name: "@foo/bar",
+ scope: "@foo",
+ type: "hosted",
+ hosted: { type: "gitlab" },
+ spec: "git+ssh://git@gitlab.com/user/foo.git",
+ rawSpec: "git+ssh://gitlab.com/user/foo",
+ raw: "@foo/bar@git+ssh://gitlab.com/user/foo"
+ }
+ }
+
+ Object.keys(tests).forEach(function (arg) {
+ var res = npa(arg)
+ t.type(res, "Result", arg + " is a result")
+ t.has(res, tests[arg], arg + " matches expectations")
+ })
+
+ t.end()
+})
--- /dev/null
+global.FAKE_WINDOWS = true
+
+var npa = require("../npa.js")
+var test = require("tap").test
+var path = require("path")
+
+var cases = {
+ "C:\\x\\y\\z": {
+ raw: "C:\\x\\y\\z",
+ scope: null,
+ name: null,
+ rawSpec: "C:\\x\\y\\z",
+ spec: path.resolve("C:\\x\\y\\z"),
+ type: "local"
+ },
+ "foo@C:\\x\\y\\z": {
+ raw: "foo@C:\\x\\y\\z",
+ scope: null,
+ name: "foo",
+ rawSpec: "C:\\x\\y\\z",
+ spec: path.resolve("C:\\x\\y\\z"),
+ type: "local"
+ },
+ "foo@/foo/bar/baz": {
+ raw: "foo@/foo/bar/baz",
+ scope: null,
+ name: "foo",
+ rawSpec: "/foo/bar/baz",
+ spec: path.resolve("/foo/bar/baz"),
+ type: "local"
+ }
+}
+
+test("parse a windows path", function (t) {
+ Object.keys(cases).forEach(function (c) {
+ var expect = cases[c]
+ var actual = npa(c)
+ t.same(actual, expect, c)
+ })
+ t.end()
+})
},
"name": "npm-registry-client",
"description": "Client for the npm registry",
- "version": "5.0.0",
+ "version": "6.0.3",
"repository": {
"url": "git://github.com/isaacs/npm-registry-client"
},
"graceful-fs": "^3.0.0",
"mkdirp": "^0.5.0",
"normalize-package-data": "~1.0.1",
+ "npm-package-arg": "^3.0.0",
"once": "^1.3.0",
"request": "^2.47.0",
"retry": "^0.6.1",
"npmlog": ""
},
"license": "ISC",
- "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)\nvar uri = \"npm://registry.npmjs.org/npm\"\nvar params = {timeout: 1000}\n\nclient.get(uri, params, function (error, 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# Registry URLs\n\nThe registry calls take either a full URL pointing to a resource in the\nregistry, or a base URL for the registry as a whole (including the registry\npath – but be sure to terminate the path with `/`). `http` and `https` URLs are\nthe only ones supported.\n\n## Using the client\n\nEvery call to the client follows the same pattern:\n\n* `uri` {String} The *fully-qualified* URI of the registry API method being\n invoked.\n* `params` {Object} Per-request parameters.\n* `callback` {Function} Callback to be invoked when the call is complete.\n\n### Credentials\n\nMany requests to the registry can by authenticated, and require credentials\nfor authorization. These credentials always look the same:\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `alwaysAuth` {Boolean} Whether calls to the target registry are always\n authed.\n\n**or**\n\n* `token` {String}\n* `alwaysAuth` {Boolean} Whether calls to the target registry are always\n authed.\n\n## API\n\n### client.adduser(uri, params, cb)\n\n* `uri` {String} Base registry URL.\n* `params` {Object} Object containing per-request properties.\n * `auth` {Credentials}\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\nAdd a user account to the registry, or verify the credentials.\n\n### client.deprecate(uri, params, cb)\n\n* `uri` {String} Full registry URI for the deprecated package.\n* `params` {Object} Object containing per-request properties.\n * `version` {String} Semver version range.\n * `message` {String} The message to use as a deprecation warning.\n * `auth` {Credentials}\n* `cb` {Function}\n\nDeprecate a version of a package in the registry.\n\n### client.get(uri, params, cb)\n\n* `uri` {String} The complete registry URI to fetch\n* `params` {Object} Object containing per-request properties.\n * `timeout` {Number} Duration before the request times out. Optional\n (default: never).\n * `follow` {Boolean} Follow 302/301 responses. Optional (default: true).\n * `staleOk` {Boolean} If there's cached data available, then return that to\n the callback quickly, and update the cache the background. Optional\n (default: false).\n * `auth` {Credentials} Optional.\n* `cb` {Function}\n\nFetches data from the registry via a GET request, saving it in the cache folder\nwith the ETag or the \"Last Modified\" timestamp.\n\n### client.publish(uri, params, cb)\n\n* `uri` {String} The registry URI for the package to publish.\n* `params` {Object} Object containing per-request properties.\n * `metadata` {Object} Package metadata.\n * `body` {Stream} Stream of the package body / tarball.\n * `auth` {Credentials}\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder.\n\n### client.star(uri, params, cb)\n\n* `uri` {String} The complete registry URI for the package to star.\n* `params` {Object} Object containing per-request properties.\n * `starred` {Boolean} True to star the package, false to unstar it. Optional\n (default: false).\n * `auth` {Credentials}\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 unstar a\npackage, though other writes do require that the user be the package owner.\n\n### client.stars(uri, params, cb)\n\n* `uri` {String} The base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `username` {String} Name of user to fetch starred packages for. Optional\n (default: user in `auth`).\n * `auth` {Credentials} Optional (required if `username` is omitted).\n* `cb` {Function}\n\nView your own or another user's starred packages.\n\n### client.tag(uri, params, cb)\n\n* `uri` {String} The complete registry URI to tag\n* `params` {Object} Object containing per-request properties.\n * `version` {String} Version to tag.\n * `tag` {String} Tag name to apply.\n * `auth` {Credentials}\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag` will fetch the\nspecified version.\n\n### client.unpublish(uri, params, cb)\n\n* `uri` {String} The complete registry URI of the package to unpublish.\n* `params` {Object} Object containing per-request properties.\n * `version` {String} version to unpublish. Optional – omit to unpublish all\n versions.\n * `auth` {Credentials}\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When the\nlast version us unpublished, the entire document is removed from the database.\n\n### client.whoami(uri, params, cb)\n\n* `uri` {String} The base registry for the URI.\n* `params` {Object} Object containing per-request properties.\n * `auth` {Credentials}\n* `cb` {Function}\n\nSimple call to see who the registry thinks you are. Especially useful with\ntoken-based auth.\n\n\n## PLUMBING\n\nThe below are primarily intended for use by the rest of the API, or by the npm\ncaching logic directly.\n\n### client.request(uri, params, cb)\n\n* `uri` {String} URI pointing to the resource to request.\n* `params` {Object} Object containing per-request properties.\n * `method` {String} HTTP method. Optional (default: \"GET\").\n * `body` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON. Optional – body\n only used for write operations.\n * `etag` {String} The cached ETag. Optional.\n * `lastModified` {String} The cached Last-Modified timestamp. Optional.\n * `follow` {Boolean} Follow 302/301 responses. Optional (default: true).\n * `auth` {Credentials} Optional.\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 generic request to the registry. All the other methods are wrappers\naround `client.request`.\n\n### client.fetch(uri, params, cb)\n\n* `uri` {String} The complete registry URI to upload to\n* `params` {Object} Object containing per-request properties.\n * `headers` {Stream} HTTP headers to be included with the request. Optional.\n * `auth` {Credentials} Optional.\n* `cb` {Function}\n\nFetch a package from a URL, with auth set appropriately if included. Used to\ncache remote tarballs as well as request package tarballs from the registry.\n\n# Configuration\n\nThe client uses its own configuration, which is just passed in as a simple\nnested object. The following are the supported values (with their defaults, if\nany):\n\n* `proxy.http` {URL} The URL to proxy HTTP requests through.\n* `proxy.https` {URL} The URL to proxy HTTPS requests through. Defaults to be\n the same as `proxy.http` if unset.\n* `proxy.localAddress` {IP} The local address to use on multi-homed systems.\n* `ssl.ca` {String} Cerficate signing authority certificates to trust.\n* `ssl.certificate` {String} Client certificate (PEM encoded). Enable access\n to servers that require client certificates.\n* `ssl.key` {String} Private key (PEM encoded) for client certificate.\n* `ssl.strict` {Boolean} Whether or not to be strict with SSL certificates.\n Default = `true`\n* `retry.count` {Number} Number of times to retry on GET failures. Default = 2.\n* `retry.factor` {Number} `factor` setting for `node-retry`. Default = 10.\n* `retry.minTimeout` {Number} `minTimeout` setting for `node-retry`.\n Default = 10000 (10 seconds)\n* `retry.maxTimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default = 60000 (60 seconds)\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* `defaultTag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `couchToken` {Object} A token for use with\n [couch-login](https://npmjs.org/package/couch-login).\n* `sessionToken` {string} A random identifier for this set of client requests.\n Default = 8 random hexadecimal bytes.\n",
+ "gitHead": "7d3d14eb825aa376c63854a08e67d2c9b3415927",
+ "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)\nvar uri = \"npm://registry.npmjs.org/npm\"\nvar params = {timeout: 1000}\n\nclient.get(uri, params, function (error, 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# Registry URLs\n\nThe registry calls take either a full URL pointing to a resource in the\nregistry, or a base URL for the registry as a whole (including the registry\npath – but be sure to terminate the path with `/`). `http` and `https` URLs are\nthe only ones supported.\n\n## Using the client\n\nEvery call to the client follows the same pattern:\n\n* `uri` {String} The *fully-qualified* URI of the registry API method being\n invoked.\n* `params` {Object} Per-request parameters.\n* `callback` {Function} Callback to be invoked when the call is complete.\n\n### Credentials\n\nMany requests to the registry can by authenticated, and require credentials\nfor authorization. These credentials always look the same:\n\n* `username` {String}\n* `password` {String}\n* `email` {String}\n* `alwaysAuth` {Boolean} Whether calls to the target registry are always\n authed.\n\n**or**\n\n* `token` {String}\n* `alwaysAuth` {Boolean} Whether calls to the target registry are always\n authed.\n\n## API\n\n### client.access(uri, params, cb)\n\n* `uri` {String} Registry URL for the package's access API endpoint.\n Looks like `/-/package/<package name>/access`.\n* `params` {Object} Object containing per-request properties.\n * `access` {String} New access level for the package. Can be either\n `public` or `restricted`. Registry will raise an error if trying\n to change the access level of an unscoped package.\n * `auth` {Credentials}\n\nSet the access level for scoped packages. For now, there are only two\naccess levels: \"public\" and \"restricted\".\n\n### client.adduser(uri, params, cb)\n\n* `uri` {String} Base registry URL.\n* `params` {Object} Object containing per-request properties.\n * `auth` {Credentials}\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\nAdd a user account to the registry, or verify the credentials.\n\n### client.deprecate(uri, params, cb)\n\n* `uri` {String} Full registry URI for the deprecated package.\n* `params` {Object} Object containing per-request properties.\n * `version` {String} Semver version range.\n * `message` {String} The message to use as a deprecation warning.\n * `auth` {Credentials}\n* `cb` {Function}\n\nDeprecate a version of a package in the registry.\n\n### client.distTags.fetch(uri, params, cb)\n\n* `uri` {String} Base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `package` {String} Name of the package.\n * `auth` {Credentials}\n* `cb` {Function}\n\nFetch all of the `dist-tags` for the named package.\n\n### client.distTags.add(uri, params, cb)\n\n* `uri` {String} Base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `package` {String} Name of the package.\n * `distTag` {String} Name of the new `dist-tag`.\n * `version` {String} Exact version to be mapped to the `dist-tag`.\n * `auth` {Credentials}\n* `cb` {Function}\n\nAdd (or replace) a single dist-tag onto the named package.\n\n### client.distTags.set(uri, params, cb)\n\n* `uri` {String} Base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `package` {String} Name of the package.\n * `distTags` {Object} Object containing a map from tag names to package\n versions.\n * `auth` {Credentials}\n* `cb` {Function}\n\nSet all of the `dist-tags` for the named package at once, creating any\n`dist-tags` that do not already exit. Any `dist-tags` not included in the\n`distTags` map will be removed.\n\n### client.distTags.update(uri, params, cb)\n\n* `uri` {String} Base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `package` {String} Name of the package.\n * `distTags` {Object} Object containing a map from tag names to package\n versions.\n * `auth` {Credentials}\n* `cb` {Function}\n\nUpdate the values of multiple `dist-tags`, creating any `dist-tags` that do\nnot already exist. Any pre-existing `dist-tags` not included in the `distTags`\nmap will be left alone.\n\n### client.distTags.rm(uri, params, cb)\n\n* `uri` {String} Base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `package` {String} Name of the package.\n * `distTag` {String} Name of the new `dist-tag`.\n * `auth` {Credentials}\n* `cb` {Function}\n\nRemove a single `dist-tag` from the named package.\n\n### client.get(uri, params, cb)\n\n* `uri` {String} The complete registry URI to fetch\n* `params` {Object} Object containing per-request properties.\n * `timeout` {Number} Duration before the request times out. Optional\n (default: never).\n * `follow` {Boolean} Follow 302/301 responses. Optional (default: true).\n * `staleOk` {Boolean} If there's cached data available, then return that to\n the callback quickly, and update the cache the background. Optional\n (default: false).\n * `auth` {Credentials} Optional.\n* `cb` {Function}\n\nFetches data from the registry via a GET request, saving it in the cache folder\nwith the ETag or the \"Last Modified\" timestamp.\n\n### client.publish(uri, params, cb)\n\n* `uri` {String} The registry URI for the package to publish.\n* `params` {Object} Object containing per-request properties.\n * `metadata` {Object} Package metadata.\n * `access` {String} Access for the package. Can be `public` or `restricted` (no default).\n * `body` {Stream} Stream of the package body / tarball.\n * `auth` {Credentials}\n* `cb` {Function}\n\nPublish a package to the registry.\n\nNote that this does not create the tarball from a folder.\n\n### client.star(uri, params, cb)\n\n* `uri` {String} The complete registry URI for the package to star.\n* `params` {Object} Object containing per-request properties.\n * `starred` {Boolean} True to star the package, false to unstar it. Optional\n (default: false).\n * `auth` {Credentials}\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 unstar a\npackage, though other writes do require that the user be the package owner.\n\n### client.stars(uri, params, cb)\n\n* `uri` {String} The base URL for the registry.\n* `params` {Object} Object containing per-request properties.\n * `username` {String} Name of user to fetch starred packages for. Optional\n (default: user in `auth`).\n * `auth` {Credentials} Optional (required if `username` is omitted).\n* `cb` {Function}\n\nView your own or another user's starred packages.\n\n### client.tag(uri, params, cb)\n\n* `uri` {String} The complete registry URI to tag\n* `params` {Object} Object containing per-request properties.\n * `version` {String} Version to tag.\n * `tag` {String} Tag name to apply.\n * `auth` {Credentials}\n* `cb` {Function}\n\nMark a version in the `dist-tags` hash, so that `pkg@tag` will fetch the\nspecified version.\n\n### client.unpublish(uri, params, cb)\n\n* `uri` {String} The complete registry URI of the package to unpublish.\n* `params` {Object} Object containing per-request properties.\n * `version` {String} version to unpublish. Optional – omit to unpublish all\n versions.\n * `auth` {Credentials}\n* `cb` {Function}\n\nRemove a version of a package (or all versions) from the registry. When the\nlast version us unpublished, the entire document is removed from the database.\n\n### client.whoami(uri, params, cb)\n\n* `uri` {String} The base registry for the URI.\n* `params` {Object} Object containing per-request properties.\n * `auth` {Credentials}\n* `cb` {Function}\n\nSimple call to see who the registry thinks you are. Especially useful with\ntoken-based auth.\n\n\n## PLUMBING\n\nThe below are primarily intended for use by the rest of the API, or by the npm\ncaching logic directly.\n\n### client.request(uri, params, cb)\n\n* `uri` {String} URI pointing to the resource to request.\n* `params` {Object} Object containing per-request properties.\n * `method` {String} HTTP method. Optional (default: \"GET\").\n * `body` {Stream | Buffer | String | Object} The request body. Objects\n that are not Buffers or Streams are encoded as JSON. Optional – body\n only used for write operations.\n * `etag` {String} The cached ETag. Optional.\n * `lastModified` {String} The cached Last-Modified timestamp. Optional.\n * `follow` {Boolean} Follow 302/301 responses. Optional (default: true).\n * `auth` {Credentials} Optional.\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 generic request to the registry. All the other methods are wrappers\naround `client.request`.\n\n### client.fetch(uri, params, cb)\n\n* `uri` {String} The complete registry URI to upload to\n* `params` {Object} Object containing per-request properties.\n * `headers` {Stream} HTTP headers to be included with the request. Optional.\n * `auth` {Credentials} Optional.\n* `cb` {Function}\n\nFetch a package from a URL, with auth set appropriately if included. Used to\ncache remote tarballs as well as request package tarballs from the registry.\n\n# Configuration\n\nThe client uses its own configuration, which is just passed in as a simple\nnested object. The following are the supported values (with their defaults, if\nany):\n\n* `proxy.http` {URL} The URL to proxy HTTP requests through.\n* `proxy.https` {URL} The URL to proxy HTTPS requests through. Defaults to be\n the same as `proxy.http` if unset.\n* `proxy.localAddress` {IP} The local address to use on multi-homed systems.\n* `ssl.ca` {String} Certificate signing authority certificates to trust.\n* `ssl.certificate` {String} Client certificate (PEM encoded). Enable access\n to servers that require client certificates.\n* `ssl.key` {String} Private key (PEM encoded) for client certificate.\n* `ssl.strict` {Boolean} Whether or not to be strict with SSL certificates.\n Default = `true`\n* `retry.count` {Number} Number of times to retry on GET failures. Default = 2.\n* `retry.factor` {Number} `factor` setting for `node-retry`. Default = 10.\n* `retry.minTimeout` {Number} `minTimeout` setting for `node-retry`.\n Default = 10000 (10 seconds)\n* `retry.maxTimeout` {Number} `maxTimeout` setting for `node-retry`.\n Default = 60000 (60 seconds)\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* `defaultTag` {String} The default tag to use when publishing new packages.\n Default = `\"latest\"`\n* `couchToken` {Object} A token for use with\n [couch-login](https://npmjs.org/package/couch-login).\n* `sessionToken` {string} A random identifier for this set of client requests.\n Default = 8 random hexadecimal bytes.\n",
"readmeFilename": "README.md",
- "gitHead": "b22f38992087e57f263c269dcd52ff290565d401",
"bugs": {
"url": "https://github.com/isaacs/npm-registry-client/issues"
},
"homepage": "https://github.com/isaacs/npm-registry-client",
- "_id": "npm-registry-client@5.0.0",
- "_shasum": "0425db2fc3dcd322e74fe95029d2c49a41e4b6cf",
- "_from": "npm-registry-client@>=5.0.0 <5.1.0"
+ "_id": "npm-registry-client@6.0.3",
+ "_shasum": "ae19f33b1cd6b4f5e81b7614bde7b97393c57cdc",
+ "_from": "npm-registry-client@>=6.0.3 <6.1.0"
}
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var URI = "http://localhost:1337/-/package/underscore/access"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var LEVEL = "public"
+var PARAMS = {
+ level : LEVEL,
+ auth : AUTH
+}
+
+test("access call contract", function (t) {
+ t.throws(function () {
+ client.access(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.access([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.access(URI, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.access(URI, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.access(URI, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.access(URI, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ auth : AUTH
+ }
+ client.access(URI, params, nop)
+ },
+ { name : "AssertionError", message : "must pass level to access" },
+ "access must include level"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ level : LEVEL
+ }
+ client.access(URI, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to access" },
+ "access must include auth"
+ )
+
+ t.end()
+})
+
+test("set access level on a package", function (t) {
+ server.expect("POST", "/-/package/underscore/access", function (req, res) {
+ t.equal(req.method, "POST")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ var updated = JSON.parse(b)
+
+ t.deepEqual(updated, { access : "public" })
+
+ res.statusCode = 201
+ res.json({accessChanged : true})
+ })
+ })
+
+ client.access(URI, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.ok(data.accessChanged, "access level set")
+
+ t.end()
+ })
+})
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var BASE_URL = "http://localhost:1337/"
+var URI = "/-/package/underscore/dist-tags/test"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var PACKAGE = "underscore"
+var DIST_TAG = "test"
+var VERSION = "3.1.3"
+var PARAMS = {
+ package : PACKAGE,
+ distTag : DIST_TAG,
+ version : VERSION,
+ auth : AUTH
+}
+
+test("distTags.add call contract", function (t) {
+ t.throws(function () {
+ client.distTags.add(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.distTags.add([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.distTags.add(BASE_URL, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.distTags.add(BASE_URL, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.distTags.add(BASE_URL, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.distTags.add(BASE_URL, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ distTag : DIST_TAG,
+ version : VERSION,
+ auth : AUTH
+ }
+ client.distTags.add(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package name to distTags.add"
+ },
+ "distTags.add must include package name"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ version : VERSION,
+ auth : AUTH
+ }
+ client.distTags.add(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package distTag name to distTags.add"
+ },
+ "distTags.add must include dist-tag"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ distTag : DIST_TAG,
+ auth : AUTH
+ }
+ client.distTags.add(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass version to be mapped to distTag to distTags.add"
+ },
+ "distTags.add must include version"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ distTag : DIST_TAG,
+ version : VERSION
+ }
+ client.distTags.add(BASE_URL, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to distTags.add" },
+ "distTags.add must include auth"
+ )
+
+ t.end()
+})
+
+test("add a new dist-tag to a package", function (t) {
+ server.expect("PUT", URI, function (req, res) {
+ t.equal(req.method, "PUT")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ t.doesNotThrow(function () {
+ var parsed = JSON.parse(b)
+ t.deepEqual(parsed, VERSION)
+
+ res.statusCode = 200
+ res.json({ "test" : VERSION })
+ }, "got valid JSON from client")
+ })
+ })
+
+ client.distTags.add(BASE_URL, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.ok(data.test, "dist-tag added")
+
+ t.end()
+ })
+})
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var BASE_URL = "http://localhost:1337/"
+var URI = "/-/package/underscore/dist-tags"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var PACKAGE = "underscore"
+var PARAMS = {
+ package : PACKAGE,
+ auth : AUTH
+}
+
+test("distTags.fetch call contract", function (t) {
+ t.throws(function () {
+ client.distTags.fetch(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.distTags.fetch([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.distTags.fetch(BASE_URL, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.distTags.fetch(BASE_URL, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.distTags.fetch(BASE_URL, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.distTags.fetch(BASE_URL, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ auth : AUTH
+ }
+ client.distTags.fetch(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package name to distTags.fetch"
+ },
+ "distTags.fetch must include package name"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE
+ }
+ client.distTags.fetch(BASE_URL, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to distTags.fetch" },
+ "distTags.fetch must include auth"
+ )
+
+ t.end()
+})
+
+test("fetch dist-tags for a package", function (t) {
+ server.expect("GET", URI, function (req, res) {
+ t.equal(req.method, "GET")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ t.notOk(b, "no request body")
+
+ res.statusCode = 200
+ res.json({ a : "1.0.0", b : "2.0.0", _etag : "xxx" })
+ })
+ })
+
+ client.distTags.fetch(BASE_URL, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.same(data, { a : "1.0.0", b : "2.0.0" }, "etag filtered from response")
+
+ t.end()
+ })
+})
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var BASE_URL = "http://localhost:1337/"
+var URI = "/-/package/underscore/dist-tags/test"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var PACKAGE = "underscore"
+var DIST_TAG = "test"
+var PARAMS = {
+ package : PACKAGE,
+ distTag : DIST_TAG,
+ auth : AUTH
+}
+
+test("distTags.rm call contract", function (t) {
+ t.throws(function () {
+ client.distTags.rm(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.distTags.rm([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.distTags.rm(BASE_URL, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.distTags.rm(BASE_URL, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.distTags.rm(BASE_URL, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.distTags.rm(BASE_URL, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ distTag : DIST_TAG,
+ auth : AUTH
+ }
+ client.distTags.rm(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package name to distTags.rm"
+ },
+ "distTags.rm must include package name"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ auth : AUTH
+ }
+ client.distTags.rm(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package distTag name to distTags.rm"
+ },
+ "distTags.rm must include dist-tag"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ distTag : DIST_TAG
+ }
+ client.distTags.rm(BASE_URL, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to distTags.rm" },
+ "distTags.rm must include auth"
+ )
+
+ t.end()
+})
+
+test("remove a dist-tag from a package", function (t) {
+ server.expect("DELETE", URI, function (req, res) {
+ t.equal(req.method, "DELETE")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ t.notOk(b, "got no message body")
+
+ res.statusCode = 200
+ res.json({})
+ })
+ })
+
+ client.distTags.rm(BASE_URL, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.notOk(data.test, "dist-tag removed")
+
+ t.end()
+ })
+})
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var BASE_URL = "http://localhost:1337/"
+var URI = "/-/package/underscore/dist-tags"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var PACKAGE = "underscore"
+var DIST_TAGS = {
+ "a" : "8.0.8",
+ "b" : "3.0.3"
+}
+var PARAMS = {
+ package : PACKAGE,
+ distTags : DIST_TAGS,
+ auth : AUTH
+}
+
+test("distTags.set call contract", function (t) {
+ t.throws(function () {
+ client.distTags.set(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.distTags.set([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.distTags.set(BASE_URL, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.distTags.set(BASE_URL, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.distTags.set(BASE_URL, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.distTags.set(BASE_URL, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ distTags : DIST_TAGS,
+ auth : AUTH
+ }
+ client.distTags.set(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package name to distTags.set"
+ },
+ "distTags.set must include package name"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ auth : AUTH
+ }
+ client.distTags.set(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass distTags map to distTags.set"
+ },
+ "distTags.set must include dist-tags"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ distTags : DIST_TAGS
+ }
+ client.distTags.set(BASE_URL, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to distTags.set" },
+ "distTags.set must include auth"
+ )
+
+ t.end()
+})
+
+test("set dist-tags for a package", function (t) {
+ server.expect("PUT", URI, function (req, res) {
+ t.equal(req.method, "PUT")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ var d = JSON.parse(b)
+ t.deepEqual(d, DIST_TAGS, "got back tags")
+
+ res.statusCode = 200
+ res.json(DIST_TAGS)
+ })
+ })
+
+ client.distTags.set(BASE_URL, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.ok(data.a && data.b, "dist-tags set")
+
+ t.end()
+ })
+})
--- /dev/null
+var test = require("tap").test
+
+var server = require("./lib/server.js")
+var common = require("./lib/common.js")
+var client = common.freshClient()
+
+function nop() {}
+
+var BASE_URL = "http://localhost:1337/"
+var URI = "/-/package/underscore/dist-tags"
+var TOKEN = "foo"
+var AUTH = {
+ token : TOKEN
+}
+var PACKAGE = "underscore"
+var DIST_TAGS = {
+ "a" : "8.0.8",
+ "b" : "3.0.3"
+}
+var PARAMS = {
+ package : PACKAGE,
+ distTags : DIST_TAGS,
+ auth : AUTH
+}
+
+test("distTags.update call contract", function (t) {
+ t.throws(function () {
+ client.distTags.update(undefined, AUTH, nop)
+ }, "requires a URI")
+
+ t.throws(function () {
+ client.distTags.update([], PARAMS, nop)
+ }, "requires URI to be a string")
+
+ t.throws(function () {
+ client.distTags.update(BASE_URL, undefined, nop)
+ }, "requires params object")
+
+ t.throws(function () {
+ client.distTags.update(BASE_URL, "", nop)
+ }, "params must be object")
+
+ t.throws(function () {
+ client.distTags.update(BASE_URL, PARAMS, undefined)
+ }, "requires callback")
+
+ t.throws(function () {
+ client.distTags.update(BASE_URL, PARAMS, "callback")
+ }, "callback must be function")
+
+ t.throws(
+ function () {
+ var params = {
+ distTags : DIST_TAGS,
+ auth : AUTH
+ }
+ client.distTags.update(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass package name to distTags.update"
+ },
+ "distTags.update must include package name"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ auth : AUTH
+ }
+ client.distTags.update(BASE_URL, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "must pass distTags map to distTags.update"
+ },
+ "distTags.update must include dist-tags"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ package : PACKAGE,
+ distTags : DIST_TAGS
+ }
+ client.distTags.update(BASE_URL, params, nop)
+ },
+ { name : "AssertionError", message : "must pass auth to distTags.update" },
+ "distTags.update must include auth"
+ )
+
+ t.end()
+})
+
+test("update dist-tags for a package", function (t) {
+ server.expect("POST", URI, function (req, res) {
+ t.equal(req.method, "POST")
+
+ var b = ""
+ req.setEncoding("utf8")
+ req.on("data", function (d) {
+ b += d
+ })
+
+ req.on("end", function () {
+ var d = JSON.parse(b)
+ t.deepEqual(d, DIST_TAGS, "got back tags")
+
+ res.statusCode = 200
+ res.json(DIST_TAGS)
+ })
+ })
+
+ client.distTags.update(BASE_URL, PARAMS, function (error, data) {
+ t.ifError(error, "no errors")
+ t.ok(data.a && data.b, "dist-tags set")
+
+ t.end()
+ })
+})
var params = {
metadata : pkg,
+ access : "restricted",
body : tarball,
auth : auth
}
var params = {
metadata : pkg,
+ access : "public",
body : tarball,
auth : auth
}
var PASSWORD = "%1234@asdf%"
var EMAIL = "i@izs.me"
var METADATA = require("../package.json")
+var ACCESS = "public"
// not really a tarball, but doesn't matter
var BODY_PATH = require.resolve("../package.json")
var BODY = createReadStream(BODY_PATH, "base64")
}
var PARAMS = {
metadata : METADATA,
+ access : ACCESS,
body : BODY,
auth : AUTH
}
var params = {
metadata : pkg,
+ access : "restricted",
body : tarball,
auth : auth
}
var params = {
metadata : pkg,
+ access : "restricted",
body : tarball,
auth : auth
}
var PASSWORD = "%1234@asdf%"
var EMAIL = "i@izs.me"
var METADATA = require("../package.json")
+var ACCESS = "public"
// not really a tarball, but doesn't matter
var BODY_PATH = require.resolve("../package.json")
var BODY = fs.createReadStream(BODY_PATH, "base64")
}
var PARAMS = {
metadata : METADATA,
+ access : ACCESS,
body : BODY,
auth : AUTH
}
t.throws(
function () {
var params = {
+ access : ACCESS,
body : BODY,
auth : AUTH
}
function () {
var params = {
metadata : METADATA,
+ body : BODY,
+ auth : AUTH
+ }
+ client.publish(URI, params, nop)
+ },
+ { name : "AssertionError", message : "must pass access for package" },
+ "params must include access for package"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ metadata : METADATA,
+ access : ACCESS,
auth : AUTH
}
client.publish(URI, params, nop)
function () {
var params = {
metadata : METADATA,
+ access : ACCESS,
body : BODY
}
client.publish(URI, params, nop)
function () {
var params = {
metadata : -1,
+ access : ACCESS,
body : BODY,
auth : AUTH
}
function () {
var params = {
metadata : METADATA,
+ access : "hamchunx",
+ body : BODY,
+ auth : AUTH
+ }
+ client.publish(URI, params, nop)
+ },
+ {
+ name : "AssertionError",
+ message : "access level must be either 'public' or 'restricted'"
+ },
+ "access level must be 'public' or 'restricted'"
+ )
+
+ t.throws(
+ function () {
+ var params = {
+ metadata : METADATA,
+ access : ACCESS,
body : -1,
auth : AUTH
}
metadata.version = "%!@#$"
var params = {
metadata : metadata,
+ access : ACCESS,
message : BODY,
auth : AUTH
}
var o = JSON.parse(b)
t.equal(o._id, "npm-registry-client")
t.equal(o["dist-tags"].latest, METADATA.version)
+ t.equal(o.access, ACCESS)
t.has(o.versions[METADATA.version], METADATA)
t.same(o.maintainers, [{ name : "username", email : "i@izs.me" }])
t.same(o.maintainers, o.versions[METADATA.version].maintainers)
client.tag(URI, params, nop)
},
{ name : "AssertionError", message : "must pass version to tag" },
- "auth must include username"
+ "tag must include version"
)
t.throws(
client.tag(URI, params, nop)
},
{ name : "AssertionError", message : "must pass tag name to tag" },
- "auth must include username"
+ "tag must include name"
)
t.throws(
client.tag(URI, params, nop)
},
{ name : "AssertionError", message : "must pass auth to tag" },
- "auth must include username"
+ "params must include auth"
)
t.end()
})
test("whoami", function (t) {
- server.expect("GET", "/whoami", function (req, res) {
+ server.expect("GET", "/-/whoami", function (req, res) {
t.equal(req.method, "GET")
// only available for token-based auth for now
- t.equal(req.headers.authorization, "Bearer not-bad-meaning-bad-but-bad-meaning-wombat")
+ t.equal(
+ req.headers.authorization,
+ "Bearer not-bad-meaning-bad-but-bad-meaning-wombat"
+ )
res.json({username : WHOIAM})
})
{
- "version": "2.3.0",
+ "version": "2.4.1",
"name": "npm",
"description": "A package manager for node",
"keywords": [
"inflight": "~1.0.4",
"inherits": "~2.0.1",
"ini": "~1.3.2",
- "init-package-json": "~1.1.3",
+ "init-package-json": "~1.2.0",
"lockfile": "~1.0.0",
"lru-cache": "~2.5.0",
"minimatch": "~2.0.1",
"npm-cache-filename": "~1.0.1",
"npm-install-checks": "~1.0.5",
"npm-package-arg": "~2.1.3",
- "npm-registry-client": "~5.0.0",
+ "npm-registry-client": "~6.0.3",
"npm-user-validate": "~0.1.1",
"npmlog": "~0.1.1",
"once": "~1.3.1",
--- /dev/null
+var fs = require("fs")
+var path = require("path")
+var mkdirp = require("mkdirp")
+var rimraf = require("rimraf")
+var mr = require("npm-registry-mock")
+
+var test = require("tap").test
+var common = require("../common-tap.js")
+
+var pkg = path.resolve(__dirname, "access")
+var server
+
+var scoped = {
+ name : "@scoped/pkg",
+ version : "1.1.1"
+}
+
+var body = {
+ access : "public"
+}
+
+function mocks (server) {
+ server.post("/-/package/@scoped%2fpkg/access", JSON.stringify(body))
+ .reply(200, { "access" : "public" })
+ server.post("/-/package/@scoped%2fanother/access", JSON.stringify(body))
+ .reply(200, { "access" : "public" })
+}
+
+test("setup", function (t) {
+ mkdirp(pkg, function (er) {
+ t.ifError(er, pkg + " made successfully")
+
+ mr({port : common.port, mocks : mocks}, function (s) {
+ server = s
+
+ fs.writeFile(
+ path.join(pkg, "package.json"),
+ JSON.stringify(scoped),
+ function (er) {
+ t.ifError(er, "wrote package.json")
+ t.end()
+ }
+ )
+ })
+ })
+})
+
+test("npm access on current package", function (t) {
+ common.npm(
+ [
+ "access",
+ "public",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+
+ t.end()
+ }
+ )
+})
+
+test("npm access on named package", function (t) {
+ common.npm(
+ [
+ "access",
+ "public", "@scoped/another",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+
+ t.end()
+ }
+ )
+})
+
+test("cleanup", function (t) {
+ t.pass("cleaned up")
+ rimraf.sync(pkg)
+ server.close()
+ t.end()
+})
--- /dev/null
+var fs = require("fs")
+var path = require("path")
+var mkdirp = require("mkdirp")
+var rimraf = require("rimraf")
+var mr = require("npm-registry-mock")
+
+var test = require("tap").test
+var common = require("../common-tap.js")
+
+var pkg = path.resolve(__dirname, "dist-tag")
+var server
+
+var scoped = {
+ name : "@scoped/pkg",
+ version : "1.1.1"
+}
+
+function mocks (server) {
+ // ls current package
+ server.get("/-/package/@scoped%2fpkg/dist-tags")
+ .reply(200, { latest : "1.0.0", a : "0.0.1", b : "0.5.0" })
+
+ // ls named package
+ server.get("/-/package/@scoped%2fanother/dist-tags")
+ .reply(200, { latest : "2.0.0", a : "0.0.2", b : "0.6.0" })
+
+ // add c
+ server.get("/-/package/@scoped%2fanother/dist-tags")
+ .reply(200, { latest : "2.0.0", a : "0.0.2", b : "0.6.0" })
+ server.put("/-/package/@scoped%2fanother/dist-tags/c", "\"7.7.7\"")
+ .reply(200, { latest : "7.7.7", a : "0.0.2", b : "0.6.0", c : "7.7.7" })
+
+ // set same version
+ server.get("/-/package/@scoped%2fanother/dist-tags")
+ .reply(200, { latest : "2.0.0", b : "0.6.0" })
+
+ // rm
+ server.get("/-/package/@scoped%2fanother/dist-tags")
+ .reply(200, { latest : "2.0.0", a : "0.0.2", b : "0.6.0", c : "7.7.7" })
+ server.delete("/-/package/@scoped%2fanother/dist-tags/c")
+ .reply(200, { c : "7.7.7" })
+
+ // rm
+ server.get("/-/package/@scoped%2fanother/dist-tags")
+ .reply(200, { latest : "4.0.0" })
+}
+
+test("setup", function (t) {
+ mkdirp(pkg, function (er) {
+ t.ifError(er, pkg + " made successfully")
+
+ mr({port : common.port, mocks : mocks}, function (s) {
+ server = s
+
+ fs.writeFile(
+ path.join(pkg, "package.json"),
+ JSON.stringify(scoped),
+ function (er) {
+ t.ifError(er, "wrote package.json")
+ t.end()
+ }
+ )
+ })
+ })
+})
+
+test("npm dist-tags ls in current package", function (t) {
+ common.npm(
+ [
+ "dist-tags", "ls",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+ t.equal(stdout, "a: 0.0.1\nb: 0.5.0\nlatest: 1.0.0\n")
+
+ t.end()
+ }
+ )
+})
+
+test("npm dist-tags ls on named package", function (t) {
+ common.npm(
+ [
+ "dist-tags",
+ "ls", "@scoped/another",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+ t.equal(stdout, "a: 0.0.2\nb: 0.6.0\nlatest: 2.0.0\n")
+
+ t.end()
+ }
+ )
+})
+
+test("npm dist-tags add @scoped/another@7.7.7 c", function (t) {
+ common.npm(
+ [
+ "dist-tags",
+ "add", "@scoped/another@7.7.7", "c",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+ t.equal(stdout, "+c: @scoped/another@7.7.7\n")
+
+ t.end()
+ }
+ )
+})
+
+test("npm dist-tags set same version", function (t) {
+ common.npm(
+ [
+ "dist-tag",
+ "set", "@scoped/another@0.6.0", "b",
+ "--registry", common.registry,
+ "--loglevel", "warn"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.equal(
+ stderr,
+ "npm WARN dist-tag add b is already set to version 0.6.0\n",
+ "warned about setting same version"
+ )
+ t.notOk(stdout, "only expecting warning message")
+
+ t.end()
+ }
+ )
+})
+
+test("npm dist-tags rm @scoped/another c", function (t) {
+ common.npm(
+ [
+ "dist-tags",
+ "rm", "@scoped/another", "c",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm access")
+ t.notOk(code, "exited OK")
+ t.notOk(stderr, "no error output")
+ t.equal(stdout, "-c: @scoped/another@7.7.7\n")
+
+ t.end()
+ }
+ )
+})
+
+test("npm dist-tags rm @scoped/another nonexistent", function (t) {
+ common.npm(
+ [
+ "dist-tags",
+ "rm", "@scoped/another", "nonexistent",
+ "--registry", common.registry,
+ "--loglevel", "silent"
+ ],
+ { cwd : pkg },
+ function (er, code, stdout, stderr) {
+ t.ifError(er, "npm dist-tag")
+ t.ok(code, "expecting nonzero exit code")
+ t.notOk(stderr, "no error output")
+ t.notOk(stdout, "not expecting output")
+
+ t.end()
+ }
+ )
+})
+
+test("cleanup", function (t) {
+ t.pass("cleaned up")
+ rimraf.sync(pkg)
+ server.close()
+ t.end()
+})
.reply(200, {_id:"underscore",_rev:2,maintainers:[jashkenas,othiym23]})
// test 4
+ server.get("/underscore")
+ .reply(200, {_id:"underscore",_rev:2,maintainers:[jashkenas,othiym23]})
server.put(
"/underscore/-rev/2",
{_id:"underscore",_rev:2,maintainers:[jashkenas]},
--- /dev/null
+var fs = require("fs")
+var path = require("path")
+
+var test = require("tap").test
+var mkdirp = require("mkdirp")
+var rimraf = require("rimraf")
+var nock = require("nock")
+
+var npm = require("../../")
+var common = require("../common-tap.js")
+
+var pkg = path.join(__dirname, "publish-access")
+
+// TODO: nock uses setImmediate, breaks 0.8: replace with mockRegistry
+if (!global.setImmediate) {
+ global.setImmediate = function () {
+ var args = [arguments[0], 0].concat([].slice.call(arguments, 1))
+ setTimeout.apply(this, args)
+ }
+}
+
+test("setup", function (t) {
+ mkdirp(path.join(pkg, "cache"), function () {
+ var configuration = {
+ cache : path.join(pkg, "cache"),
+ loglevel : "silent",
+ registry : common.registry
+ }
+
+ npm.load(configuration, next)
+ })
+
+ function next (er) {
+ t.ifError(er, "npm loaded successfully")
+
+ process.chdir(pkg)
+ fs.writeFile(
+ path.join(pkg, "package.json"),
+ JSON.stringify({
+ name: "@bigco/publish-access",
+ version: "1.2.5"
+ }),
+ "ascii",
+ function (er) {
+ t.ifError(er)
+
+ t.pass("setup done")
+ t.end()
+ }
+ )
+ }
+})
+
+test("scoped packages should default to restricted access", function (t) {
+ var put = nock(common.registry)
+ .put("/@bigco%2fpublish-access")
+ .reply(201, verify)
+
+ npm.commands.publish([], false, function (er) {
+ t.ifError(er, "published without error")
+
+ put.done()
+ t.end()
+ })
+
+ function verify (_, body) {
+ t.doesNotThrow(function () {
+ var parsed = JSON.parse(body)
+ t.equal(parsed.access, "restricted", "access level is correct")
+ }, "converted body back into object")
+
+ return {ok: true}
+ }
+})
+
+test("cleanup", function (t) {
+ process.chdir(__dirname)
+ rimraf(pkg, function (er) {
+ t.ifError(er)
+
+ t.end()
+ })
+})
--- /dev/null
+var fs = require("fs")
+var path = require("path")
+
+var test = require("tap").test
+var mkdirp = require("mkdirp")
+var rimraf = require("rimraf")
+var nock = require("nock")
+
+var npm = require("../../")
+var common = require("../common-tap.js")
+
+var pkg = path.join(__dirname, "publish-access-unscoped")
+
+// TODO: nock uses setImmediate, breaks 0.8: replace with mockRegistry
+if (!global.setImmediate) {
+ global.setImmediate = function () {
+ var args = [arguments[0], 0].concat([].slice.call(arguments, 1))
+ setTimeout.apply(this, args)
+ }
+}
+
+test("setup", function (t) {
+ mkdirp(path.join(pkg, "cache"), function () {
+ var configuration = {
+ cache : path.join(pkg, "cache"),
+ loglevel : "silent",
+ registry : common.registry
+ }
+
+ npm.load(configuration, next)
+ })
+
+ function next (er) {
+ t.ifError(er, "npm loaded successfully")
+
+ process.chdir(pkg)
+ fs.writeFile(
+ path.join(pkg, "package.json"),
+ JSON.stringify({
+ name: "publish-access",
+ version: "1.2.5"
+ }),
+ "ascii",
+ function (er) {
+ t.ifError(er)
+
+ t.pass("setup done")
+ t.end()
+ }
+ )
+ }
+})
+
+test("scoped packages should default to restricted access", function (t) {
+ var put = nock(common.registry)
+ .put("/publish-access")
+ .reply(201, verify)
+
+ npm.commands.publish([], false, function (er) {
+ t.ifError(er, "published without error")
+
+ put.done()
+ t.end()
+ })
+
+ function verify (_, body) {
+ t.doesNotThrow(function () {
+ var parsed = JSON.parse(body)
+ t.equal(parsed.access, "public", "access level is correct")
+ }, "converted body back into object")
+
+ return {ok: true}
+ }
+})
+
+test("cleanup", function (t) {
+ process.chdir(__dirname)
+ rimraf(pkg, function (er) {
+ t.ifError(er)
+
+ t.end()
+ })
+})