1# libnpmhook [![npm version](https://img.shields.io/npm/v/libnpmhook.svg)](https://npm.im/libnpmhook) [![license](https://img.shields.io/npm/l/libnpmhook.svg)](https://npm.im/libnpmhook) [![Travis](https://img.shields.io/travis/npm/libnpmhook.svg)](https://travis-ci.org/npm/libnpmhook) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/libnpmhook?svg=true)](https://ci.appveyor.com/project/zkat/libnpmhook) [![Coverage Status](https://coveralls.io/repos/github/npm/libnpmhook/badge.svg?branch=latest)](https://coveralls.io/github/npm/libnpmhook?branch=latest) 2 3[`libnpmhook`](https://github.com/npm/libnpmhook) is a Node.js library for 4programmatically managing the npm registry's server-side hooks. 5 6For a more general introduction to managing hooks, see [the introductory blog 7post](https://blog.npmjs.org/post/145260155635/introducing-hooks-get-notifications-of-npm). 8 9## Example 10 11```js 12const hooks = require('libnpmhook') 13 14console.log(await hooks.ls('mypkg', {token: 'deadbeef'})) 15// array of hook objects on `mypkg`. 16``` 17 18## Install 19 20`$ npm install libnpmhook` 21 22## Table of Contents 23 24* [Example](#example) 25* [Install](#install) 26* [API](#api) 27 * [hook opts](#opts) 28 * [`add()`](#add) 29 * [`rm()`](#rm) 30 * [`ls()`](#ls) 31 * [`ls.stream()`](#ls-stream) 32 * [`update()`](#update) 33 34### API 35 36#### <a name="opts"></a> `opts` for `libnpmhook` commands 37 38`libnpmhook` uses [`npm-registry-fetch`](https://npm.im/npm-registry-fetch). 39All options are passed through directly to that library, so please refer to [its 40own `opts` 41documentation](https://www.npmjs.com/package/npm-registry-fetch#fetch-options) 42for options that can be passed in. 43 44A couple of options of note for those in a hurry: 45 46* `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. 47* `opts.otp` - certain operations will require an OTP token to be passed in. If a `libnpmhook` command fails with `err.code === EOTP`, please retry the request with `{otp: <2fa token>}` 48* `opts.Promise` - If you pass this in, the Promises returned by `libnpmhook` commands will use this Promise class instead. For example: `{Promise: require('bluebird')}` 49 50#### <a name="add"></a> `> hooks.add(name, endpoint, secret, [opts]) -> Promise` 51 52`name` is the name of the package, org, or user/org scope to watch. The type is 53determined by the name syntax: `'@foo/bar'` and `'foo'` are treated as packages, 54`@foo` is treated as a scope, and `~user` is treated as an org name or scope. 55Each type will attach to different events. 56 57The `endpoint` should be a fully-qualified http URL for the endpoint the hook 58will send its payload to when it fires. `secret` is a shared secret that the 59hook will send to that endpoint to verify that it's actually coming from the 60registry hook. 61 62The returned Promise resolves to the full hook object that was created, 63including its generated `id`. 64 65See also: [`POST 66/v1/hooks/hook`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#post-v1hookshook) 67 68##### Example 69 70```javascript 71await hooks.add('~zkat', 'https://zkat.tech/api/added', 'supersekrit', { 72 token: 'myregistrytoken', 73 otp: '694207' 74}) 75 76=> 77 78{ id: '16f7xoal', 79 username: 'zkat', 80 name: 'zkat', 81 endpoint: 'https://zkat.tech/api/added', 82 secret: 'supersekrit', 83 type: 'owner', 84 created: '2018-08-21T20:05:25.125Z', 85 updated: '2018-08-21T20:05:25.125Z', 86 deleted: false, 87 delivered: false, 88 last_delivery: null, 89 response_code: 0, 90 status: 'active' } 91``` 92 93#### <a name="find"></a> `> hooks.find(id, [opts]) -> Promise` 94 95Returns the hook identified by `id`. 96 97The returned Promise resolves to the full hook object that was found, or error 98with `err.code` of `'E404'` if it didn't exist. 99 100See also: [`GET 101/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hookshookid) 102 103##### Example 104 105```javascript 106await hooks.find('16f7xoal', {token: 'myregistrytoken'}) 107 108=> 109 110{ id: '16f7xoal', 111 username: 'zkat', 112 name: 'zkat', 113 endpoint: 'https://zkat.tech/api/added', 114 secret: 'supersekrit', 115 type: 'owner', 116 created: '2018-08-21T20:05:25.125Z', 117 updated: '2018-08-21T20:05:25.125Z', 118 deleted: false, 119 delivered: false, 120 last_delivery: null, 121 response_code: 0, 122 status: 'active' } 123``` 124 125#### <a name="rm"></a> `> hooks.rm(id, [opts]) -> Promise` 126 127Removes the hook identified by `id`. 128 129The returned Promise resolves to the full hook object that was removed, if it 130existed, or `null` if no such hook was there (instead of erroring). 131 132See also: [`DELETE 133/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#delete-v1hookshookid) 134 135##### Example 136 137```javascript 138await hooks.rm('16f7xoal', { 139 token: 'myregistrytoken', 140 otp: '694207' 141}) 142 143=> 144 145{ id: '16f7xoal', 146 username: 'zkat', 147 name: 'zkat', 148 endpoint: 'https://zkat.tech/api/added', 149 secret: 'supersekrit', 150 type: 'owner', 151 created: '2018-08-21T20:05:25.125Z', 152 updated: '2018-08-21T20:05:25.125Z', 153 deleted: true, 154 delivered: false, 155 last_delivery: null, 156 response_code: 0, 157 status: 'active' } 158 159// Repeat it... 160await hooks.rm('16f7xoal', { 161 token: 'myregistrytoken', 162 otp: '694207' 163}) 164 165=> null 166``` 167 168#### <a name="update"></a> `> hooks.update(id, endpoint, secret, [opts]) -> Promise` 169 170The `id` should be a hook ID from a previously-created hook. 171 172The `endpoint` should be a fully-qualified http URL for the endpoint the hook 173will send its payload to when it fires. `secret` is a shared secret that the 174hook will send to that endpoint to verify that it's actually coming from the 175registry hook. 176 177The returned Promise resolves to the full hook object that was updated, if it 178existed. Otherwise, it will error with an `'E404'` error code. 179 180See also: [`PUT 181/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#put-v1hookshookid) 182 183##### Example 184 185```javascript 186await hooks.update('16fxoal', 'https://zkat.tech/api/other', 'newsekrit', { 187 token: 'myregistrytoken', 188 otp: '694207' 189}) 190 191=> 192 193{ id: '16f7xoal', 194 username: 'zkat', 195 name: 'zkat', 196 endpoint: 'https://zkat.tech/api/other', 197 secret: 'newsekrit', 198 type: 'owner', 199 created: '2018-08-21T20:05:25.125Z', 200 updated: '2018-08-21T20:14:41.964Z', 201 deleted: false, 202 delivered: false, 203 last_delivery: null, 204 response_code: 0, 205 status: 'active' } 206``` 207 208#### <a name="ls"></a> `> hooks.ls([opts]) -> Promise` 209 210Resolves to an array of hook objects associated with the account you're 211authenticated as. 212 213Results can be further filtered with three values that can be passed in through 214`opts`: 215 216* `opts.package` - filter results by package name 217* `opts.limit` - maximum number of hooks to return 218* `opts.offset` - pagination offset for results (use with `opts.limit`) 219 220See also: 221 * [`hooks.ls.stream()`](#ls-stream) 222 * [`GET 223/v1/hooks`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hooks) 224 225##### Example 226 227```javascript 228await hooks.ls({token: 'myregistrytoken'}) 229 230=> 231[ 232 { id: '16f7xoal', ... }, 233 { id: 'wnyf98a1', ... }, 234 ... 235] 236``` 237 238#### <a name="ls-stream"></a> `> hooks.ls.stream([opts]) -> Stream` 239 240Returns a stream of hook objects associated with the account you're 241authenticated as. The returned stream is a valid `Symbol.asyncIterator` on 242`node@>=10`. 243 244Results can be further filtered with three values that can be passed in through 245`opts`: 246 247* `opts.package` - filter results by package name 248* `opts.limit` - maximum number of hooks to return 249* `opts.offset` - pagination offset for results (use with `opts.limit`) 250 251See also: 252 * [`hooks.ls()`](#ls) 253 * [`GET 254/v1/hooks`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hooks) 255 256##### Example 257 258```javascript 259for await (let hook of hooks.ls.stream({token: 'myregistrytoken'})) { 260 console.log('found hook:', hook.id) 261} 262 263=> 264// outputs: 265// found hook: 16f7xoal 266// found hook: wnyf98a1 267``` 268