# libnpmorg
[![npm version](https://img.shields.io/npm/v/libnpmorg.svg)](https://npm.im/libnpmorg)
[![license](https://img.shields.io/npm/l/libnpmorg.svg)](https://npm.im/libnpmorg)
[![CI - libnpmorg](https://github.com/npm/cli/actions/workflows/ci-libnpmorg.yml/badge.svg)](https://github.com/npm/cli/actions/workflows/ci-libnpmorg.yml)
[`libnpmorg`](https://github.com/npm/libnpmorg) is a Node.js library for
programmatically accessing the [npm Org membership
API](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#membership-detail).
## Table of Contents
* [Example](#example)
* [Install](#install)
* [Contributing](#contributing)
* [API](#api)
* [hook opts](#opts)
* [`set()`](#set)
* [`rm()`](#rm)
* [`ls()`](#ls)
* [`ls.stream()`](#ls-stream)
## Example
```js
const org = require('libnpmorg')
console.log(await org.ls('myorg', {token: 'deadbeef'}))
=>
Roster {
zkat: 'developer',
iarna: 'admin',
isaacs: 'owner'
}
```
## Install
`$ npm install libnpmorg`
### API
#### `opts` for `libnpmorg` commands
`libnpmorg` uses [`npm-registry-fetch`](https://npm.im/npm-registry-fetch).
All options are passed through directly to that library, so please refer to [its
own `opts`
documentation](https://www.npmjs.com/package/npm-registry-fetch#fetch-options)
for options that can be passed in.
A couple of options of note for those in a hurry:
* `opts.token` - can be passed in and will be used as the authentication token for the registry. For other ways to pass in auth details, see the n-r-f docs.
* `opts.otp` - certain operations will require an OTP token to be passed in. If a `libnpmorg` command fails with `err.code === EOTP`, please retry the request with `{otp: <2fa token>}`
#### `> org.set(org, user, [role], [opts]) -> Promise`
The returned Promise resolves to a [Membership
Detail](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#membership-detail)
object.
The `role` is optional and should be one of `admin`, `owner`, or `developer`.
`developer` is the default if no `role` is provided.
`org` and `user` must be scope names for the org name and user name
respectively. They can optionally be prefixed with `@`.
See also: [`PUT
/-/org/:scope/user`](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#org-membership-replace)
##### Example
```javascript
await org.set('@myorg', '@myuser', 'admin', {token: 'deadbeef'})
=>
MembershipDetail {
org: {
name: 'myorg',
size: 15
},
user: 'myuser',
role: 'admin'
}
```
#### `> org.rm(org, user, [opts]) -> Promise`
The Promise resolves to `null` on success.
`org` and `user` must be scope names for the org name and user name
respectively. They can optionally be prefixed with `@`.
See also: [`DELETE
/-/org/:scope/user`](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#org-membership-delete)
##### Example
```javascript
await org.rm('myorg', 'myuser', {token: 'deadbeef'})
```
#### `> org.ls(org, [opts]) -> Promise`
The Promise resolves to a
[Roster](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#roster)
object.
`org` must be a scope name for an org, and can be optionally prefixed with `@`.
See also: [`GET
/-/org/:scope/user`](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#org-roster)
##### Example
```javascript
await org.ls('myorg', {token: 'deadbeef'})
=>
Roster {
zkat: 'developer',
iarna: 'admin',
isaacs: 'owner'
}
```
#### `> org.ls.stream(org, [opts]) -> Stream`
Returns a stream of entries for a
[Roster](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#roster),
with each emitted entry in `[key, value]` format.
`org` must be a scope name for an org, and can be optionally prefixed with `@`.
The returned stream is a valid `Symbol.asyncIterator`.
See also: [`GET
/-/org/:scope/user`](https://github.com/npm/registry/blob/master/docs/orgs/memberships.md#org-roster)
##### Example
```javascript
for await (let [user, role] of org.ls.stream('myorg', {token: 'deadbeef'})) {
console.log(`user: ${user} (${role})`)
}
=>
user: zkat (developer)
user: iarna (admin)
user: isaacs (owner)
```