Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Fritz <fritzy@github.com>2021-12-16 21:01:56 +0300
committerNathan Fritz <fritzy@github.com>2021-12-16 21:05:19 +0300
commitd7265045730555c03b3142c004c7438e9577028c (patch)
tree035d81b3124bdaa09c21854934bf2b2b50e52e44 /workspaces/libnpmhook
parentd8aac8448e983692cacb427e03f4688cd1b62e30 (diff)
Bring in all libnpm modules + arborist as workspaces (#4166)
Added libnpm workspaces and arborist
Diffstat (limited to 'workspaces/libnpmhook')
-rw-r--r--workspaces/libnpmhook/.eslintrc.js14
-rw-r--r--workspaces/libnpmhook/.gitignore23
-rw-r--r--workspaces/libnpmhook/.npmrc3
-rw-r--r--workspaces/libnpmhook/CHANGELOG.md110
-rw-r--r--workspaces/libnpmhook/LICENSE.md16
-rw-r--r--workspaces/libnpmhook/README.md271
-rw-r--r--workspaces/libnpmhook/SECURITY.md3
-rw-r--r--workspaces/libnpmhook/lib/index.js70
-rw-r--r--workspaces/libnpmhook/package.json49
-rw-r--r--workspaces/libnpmhook/test/fixtures/tnock.js12
-rw-r--r--workspaces/libnpmhook/test/index.js267
11 files changed, 838 insertions, 0 deletions
diff --git a/workspaces/libnpmhook/.eslintrc.js b/workspaces/libnpmhook/.eslintrc.js
new file mode 100644
index 000000000..022767bc3
--- /dev/null
+++ b/workspaces/libnpmhook/.eslintrc.js
@@ -0,0 +1,14 @@
+// This file is automatically added by @npmcli/template-oss. Do not edit.
+
+const { readdirSync: readdir } = require('fs')
+
+const localConfigs = readdir(__dirname)
+ .filter((file) => file.startsWith('.eslintrc.local.'))
+ .map((file) => `./${file}`)
+
+module.exports = {
+ extends: [
+ '@npmcli',
+ ...localConfigs,
+ ],
+}
diff --git a/workspaces/libnpmhook/.gitignore b/workspaces/libnpmhook/.gitignore
new file mode 100644
index 000000000..6ed44c72b
--- /dev/null
+++ b/workspaces/libnpmhook/.gitignore
@@ -0,0 +1,23 @@
+# This file is automatically added by @npmcli/template-oss. Do not edit.
+
+# ignore everything in the root
+/*
+
+# keep these
+!/.commitlintrc.js
+!/.npmrc
+!/.eslintrc*
+!/.github
+!**/.gitignore
+!/package.json
+!/docs
+!/bin
+!/lib
+!/map.js
+!/tap-snapshots
+!/test
+!/scripts
+!/README*
+!/LICENSE*
+!/SECURITY*
+!/CHANGELOG*
diff --git a/workspaces/libnpmhook/.npmrc b/workspaces/libnpmhook/.npmrc
new file mode 100644
index 000000000..878b7ddef
--- /dev/null
+++ b/workspaces/libnpmhook/.npmrc
@@ -0,0 +1,3 @@
+;This file is automatically added by @npmcli/template-oss. Do not edit.
+
+package-lock=false
diff --git a/workspaces/libnpmhook/CHANGELOG.md b/workspaces/libnpmhook/CHANGELOG.md
new file mode 100644
index 000000000..055727497
--- /dev/null
+++ b/workspaces/libnpmhook/CHANGELOG.md
@@ -0,0 +1,110 @@
+# Change Log
+
+<a name="6.0.0"></a>
+# [6.0.0](https://github.com/npm/libnpmhook/compare/v5.0.2...v6.0.0) (2020-02-26)
+
+### Breaking Changes
+
+* [`aa629b4`](https://github.com/npm/libnpmhook/commit/aa629b4) fix: remove figgy-pudding ([@claudiahdz](https://github.com/claudiahdz))
+
+### Miscellaneuous
+
+* [`ea795fb`](https://github.com/npm/libnpmhook/commit/ea795fb) chore: basic project updates ([@claudiahdz](https://github.com/claudiahdz))
+* [`a0fdf7e`](https://github.com/npm/libnpmhook/commit/a0fdf7e) chore: cleanup badges, contrib, readme ([@ruyadorno](https://github.com/ruyadorno))
+
+---
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+<a name="5.0.2"></a>
+## [5.0.2](https://github.com/npm/libnpmhook/compare/v5.0.1...v5.0.2) (2018-08-24)
+
+
+
+<a name="5.0.1"></a>
+## [5.0.1](https://github.com/npm/libnpmhook/compare/v5.0.0...v5.0.1) (2018-08-23)
+
+
+### Bug Fixes
+
+* **deps:** move JSONStream to prod deps ([bb63594](https://github.com/npm/libnpmhook/commit/bb63594))
+
+
+
+<a name="5.0.0"></a>
+# [5.0.0](https://github.com/npm/libnpmhook/compare/v4.0.1...v5.0.0) (2018-08-21)
+
+
+### Features
+
+* **api:** overhauled API ([46b271b](https://github.com/npm/libnpmhook/commit/46b271b))
+
+
+### BREAKING CHANGES
+
+* **api:** the API for ls() has changed, and rm() no longer errors on 404
+
+
+
+<a name="4.0.1"></a>
+## [4.0.1](https://github.com/npm/libnpmhook/compare/v4.0.0...v4.0.1) (2018-04-09)
+
+
+
+<a name="4.0.0"></a>
+# [4.0.0](https://github.com/npm/libnpmhook/compare/v3.0.1...v4.0.0) (2018-04-08)
+
+
+### meta
+
+* drop support for node 4 and 7 ([f2a301e](https://github.com/npm/libnpmhook/commit/f2a301e))
+
+
+### BREAKING CHANGES
+
+* node@4 and node@7 are no longer supported
+
+
+
+<a name="3.0.1"></a>
+## [3.0.1](https://github.com/npm/libnpmhook/compare/v3.0.0...v3.0.1) (2018-04-08)
+
+
+
+<a name="3.0.0"></a>
+# [3.0.0](https://github.com/npm/libnpmhook/compare/v2.0.1...v3.0.0) (2018-04-04)
+
+
+### add
+
+* guess type based on name ([9418224](https://github.com/npm/libnpmhook/commit/9418224))
+
+
+### BREAKING CHANGES
+
+* hook type is now based on name prefix
+
+
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/npm/libnpmhook/compare/v2.0.0...v2.0.1) (2018-03-16)
+
+
+### Bug Fixes
+
+* **urls:** was hitting the wrong URL endpoints ([10171a9](https://github.com/npm/libnpmhook/commit/10171a9))
+
+
+
+<a name="2.0.0"></a>
+# [2.0.0](https://github.com/npm/libnpmhook/compare/v1.0.0...v2.0.0) (2018-03-16)
+
+
+
+<a name="1.0.0"></a>
+# 1.0.0 (2018-03-16)
+
+
+### Features
+
+* **api:** baseline working api ([122658e](https://github.com/npm/npm-hooks/commit/122658e))
diff --git a/workspaces/libnpmhook/LICENSE.md b/workspaces/libnpmhook/LICENSE.md
new file mode 100644
index 000000000..8d28acf86
--- /dev/null
+++ b/workspaces/libnpmhook/LICENSE.md
@@ -0,0 +1,16 @@
+ISC License
+
+Copyright (c) npm, Inc.
+
+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 COPYRIGHT HOLDER DISCLAIMS
+ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER 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.
diff --git a/workspaces/libnpmhook/README.md b/workspaces/libnpmhook/README.md
new file mode 100644
index 000000000..ce6e8c1a5
--- /dev/null
+++ b/workspaces/libnpmhook/README.md
@@ -0,0 +1,271 @@
+# 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)
+[![Coverage Status](https://coveralls.io/repos/github/npm/libnpmhook/badge.svg?branch=latest)](https://coveralls.io/github/npm/libnpmhook?branch=latest)
+
+[`libnpmhook`](https://github.com/npm/libnpmhook) is a Node.js library for
+programmatically managing the npm registry's server-side hooks.
+
+For a more general introduction to managing hooks, see [the introductory blog
+post](https://blog.npmjs.org/post/145260155635/introducing-hooks-get-notifications-of-npm).
+
+## Table of Contents
+
+* [Example](#example)
+* [Install](#install)
+* [Contributing](#contributing)
+* [API](#api)
+ * [hook opts](#opts)
+ * [`add()`](#add)
+ * [`rm()`](#rm)
+ * [`ls()`](#ls)
+ * [`ls.stream()`](#ls-stream)
+ * [`update()`](#update)
+
+## Example
+
+```js
+const hooks = require('libnpmhook')
+
+console.log(await hooks.ls('mypkg', {token: 'deadbeef'}))
+// array of hook objects on `mypkg`.
+```
+
+## Install
+
+`$ npm install libnpmhook`
+
+### API
+
+#### <a name="opts"></a> `opts` for `libnpmhook` commands
+
+`libnpmhook` 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 `libnpmhook` command fails with `err.code === EOTP`, please retry the request with `{otp: <2fa token>}`
+
+#### <a name="add"></a> `> hooks.add(name, endpoint, secret, [opts]) -> Promise`
+
+`name` is the name of the package, org, or user/org scope to watch. The type is
+determined by the name syntax: `'@foo/bar'` and `'foo'` are treated as packages,
+`@foo` is treated as a scope, and `~user` is treated as an org name or scope.
+Each type will attach to different events.
+
+The `endpoint` should be a fully-qualified http URL for the endpoint the hook
+will send its payload to when it fires. `secret` is a shared secret that the
+hook will send to that endpoint to verify that it's actually coming from the
+registry hook.
+
+The returned Promise resolves to the full hook object that was created,
+including its generated `id`.
+
+See also: [`POST
+/v1/hooks/hook`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#post-v1hookshook)
+
+##### Example
+
+```javascript
+await hooks.add('~zkat', 'https://example.com/api/added', 'supersekrit', {
+ token: 'myregistrytoken',
+ otp: '694207'
+})
+
+=>
+
+{ id: '16f7xoal',
+ username: 'zkat',
+ name: 'zkat',
+ endpoint: 'https://example.com/api/added',
+ secret: 'supersekrit',
+ type: 'owner',
+ created: '2018-08-21T20:05:25.125Z',
+ updated: '2018-08-21T20:05:25.125Z',
+ deleted: false,
+ delivered: false,
+ last_delivery: null,
+ response_code: 0,
+ status: 'active' }
+```
+
+#### <a name="find"></a> `> hooks.find(id, [opts]) -> Promise`
+
+Returns the hook identified by `id`.
+
+The returned Promise resolves to the full hook object that was found, or error
+with `err.code` of `'E404'` if it didn't exist.
+
+See also: [`GET
+/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hookshookid)
+
+##### Example
+
+```javascript
+await hooks.find('16f7xoal', {token: 'myregistrytoken'})
+
+=>
+
+{ id: '16f7xoal',
+ username: 'zkat',
+ name: 'zkat',
+ endpoint: 'https://example.com/api/added',
+ secret: 'supersekrit',
+ type: 'owner',
+ created: '2018-08-21T20:05:25.125Z',
+ updated: '2018-08-21T20:05:25.125Z',
+ deleted: false,
+ delivered: false,
+ last_delivery: null,
+ response_code: 0,
+ status: 'active' }
+```
+
+#### <a name="rm"></a> `> hooks.rm(id, [opts]) -> Promise`
+
+Removes the hook identified by `id`.
+
+The returned Promise resolves to the full hook object that was removed, if it
+existed, or `null` if no such hook was there (instead of erroring).
+
+See also: [`DELETE
+/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#delete-v1hookshookid)
+
+##### Example
+
+```javascript
+await hooks.rm('16f7xoal', {
+ token: 'myregistrytoken',
+ otp: '694207'
+})
+
+=>
+
+{ id: '16f7xoal',
+ username: 'zkat',
+ name: 'zkat',
+ endpoint: 'https://example.com/api/added',
+ secret: 'supersekrit',
+ type: 'owner',
+ created: '2018-08-21T20:05:25.125Z',
+ updated: '2018-08-21T20:05:25.125Z',
+ deleted: true,
+ delivered: false,
+ last_delivery: null,
+ response_code: 0,
+ status: 'active' }
+
+// Repeat it...
+await hooks.rm('16f7xoal', {
+ token: 'myregistrytoken',
+ otp: '694207'
+})
+
+=> null
+```
+
+#### <a name="update"></a> `> hooks.update(id, endpoint, secret, [opts]) -> Promise`
+
+The `id` should be a hook ID from a previously-created hook.
+
+The `endpoint` should be a fully-qualified http URL for the endpoint the hook
+will send its payload to when it fires. `secret` is a shared secret that the
+hook will send to that endpoint to verify that it's actually coming from the
+registry hook.
+
+The returned Promise resolves to the full hook object that was updated, if it
+existed. Otherwise, it will error with an `'E404'` error code.
+
+See also: [`PUT
+/v1/hooks/hook/:id`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#put-v1hookshookid)
+
+##### Example
+
+```javascript
+await hooks.update('16fxoal', 'https://example.com/api/other', 'newsekrit', {
+ token: 'myregistrytoken',
+ otp: '694207'
+})
+
+=>
+
+{ id: '16f7xoal',
+ username: 'zkat',
+ name: 'zkat',
+ endpoint: 'https://example.com/api/other',
+ secret: 'newsekrit',
+ type: 'owner',
+ created: '2018-08-21T20:05:25.125Z',
+ updated: '2018-08-21T20:14:41.964Z',
+ deleted: false,
+ delivered: false,
+ last_delivery: null,
+ response_code: 0,
+ status: 'active' }
+```
+
+#### <a name="ls"></a> `> hooks.ls([opts]) -> Promise`
+
+Resolves to an array of hook objects associated with the account you're
+authenticated as.
+
+Results can be further filtered with three values that can be passed in through
+`opts`:
+
+* `opts.package` - filter results by package name
+* `opts.limit` - maximum number of hooks to return
+* `opts.offset` - pagination offset for results (use with `opts.limit`)
+
+See also:
+ * [`hooks.ls.stream()`](#ls-stream)
+ * [`GET
+/v1/hooks`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hooks)
+
+##### Example
+
+```javascript
+await hooks.ls({token: 'myregistrytoken'})
+
+=>
+[
+ { id: '16f7xoal', ... },
+ { id: 'wnyf98a1', ... },
+ ...
+]
+```
+
+#### <a name="ls-stream"></a> `> hooks.ls.stream([opts]) -> Stream`
+
+Returns a stream of hook objects associated with the account you're
+authenticated as. The returned stream is a valid `Symbol.asyncIterator` on
+`node@>=10`.
+
+Results can be further filtered with three values that can be passed in through
+`opts`:
+
+* `opts.package` - filter results by package name
+* `opts.limit` - maximum number of hooks to return
+* `opts.offset` - pagination offset for results (use with `opts.limit`)
+
+See also:
+ * [`hooks.ls()`](#ls)
+ * [`GET
+/v1/hooks`](https://github.com/npm/registry/blob/master/docs/hooks/endpoints.md#get-v1hooks)
+
+##### Example
+
+```javascript
+for await (let hook of hooks.ls.stream({token: 'myregistrytoken'})) {
+ console.log('found hook:', hook.id)
+}
+
+=>
+// outputs:
+// found hook: 16f7xoal
+// found hook: wnyf98a1
+```
diff --git a/workspaces/libnpmhook/SECURITY.md b/workspaces/libnpmhook/SECURITY.md
new file mode 100644
index 000000000..a93106d0c
--- /dev/null
+++ b/workspaces/libnpmhook/SECURITY.md
@@ -0,0 +1,3 @@
+<!-- This file is automatically added by @npmcli/template-oss. Do not edit. -->
+
+Please send vulnerability reports through [hackerone](https://hackerone.com/github).
diff --git a/workspaces/libnpmhook/lib/index.js b/workspaces/libnpmhook/lib/index.js
new file mode 100644
index 000000000..7cd18261d
--- /dev/null
+++ b/workspaces/libnpmhook/lib/index.js
@@ -0,0 +1,70 @@
+'use strict'
+
+const fetch = require('npm-registry-fetch')
+const validate = require('aproba')
+
+const eu = encodeURIComponent
+const cmd = module.exports = {}
+cmd.add = (name, endpoint, secret, opts = {}) => {
+ validate('SSSO', [name, endpoint, secret, opts])
+ let type = 'package'
+ if (name.match(/^@[^/]+$/)) {
+ type = 'scope'
+ }
+ if (name[0] === '~') {
+ type = 'owner'
+ name = name.substr(1)
+ }
+ return fetch.json('/-/npm/v1/hooks/hook', {
+ ...opts,
+ method: 'POST',
+ body: { type, name, endpoint, secret },
+ })
+}
+
+cmd.rm = (id, opts = {}) => {
+ validate('SO', [id, opts])
+ return fetch.json(`/-/npm/v1/hooks/hook/${eu(id)}`, {
+ ...opts,
+ method: 'DELETE',
+ }).catch(err => {
+ if (err.code === 'E404') {
+ return null
+ } else {
+ throw err
+ }
+ })
+}
+
+cmd.update = (id, endpoint, secret, opts = {}) => {
+ validate('SSSO', [id, endpoint, secret, opts])
+ return fetch.json(`/-/npm/v1/hooks/hook/${eu(id)}`, {
+ ...opts,
+ method: 'PUT',
+ body: { endpoint, secret },
+ })
+}
+
+cmd.find = (id, opts = {}) => {
+ validate('SO', [id, opts])
+ return fetch.json(`/-/npm/v1/hooks/hook/${eu(id)}`, opts)
+}
+
+cmd.ls = (opts = {}) => {
+ return cmd.ls.stream(opts).collect()
+}
+
+cmd.ls.stream = (opts = {}) => {
+ const { package: pkg, limit, offset } = opts
+ validate('S|Z', [pkg])
+ validate('N|Z', [limit])
+ validate('N|Z', [offset])
+ return fetch.json.stream('/-/npm/v1/hooks', 'objects.*', {
+ ...opts,
+ query: {
+ package: pkg,
+ limit,
+ offset,
+ },
+ })
+}
diff --git a/workspaces/libnpmhook/package.json b/workspaces/libnpmhook/package.json
new file mode 100644
index 000000000..4580aea64
--- /dev/null
+++ b/workspaces/libnpmhook/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "libnpmhook",
+ "version": "7.0.0",
+ "description": "programmatic API for managing npm registry hooks",
+ "main": "lib/index.js",
+ "files": [
+ "bin",
+ "lib"
+ ],
+ "scripts": {
+ "prerelease": "npm t",
+ "postrelease": "npm publish && git push --follow-tags",
+ "test": "tap",
+ "lint": "eslint '**/*.js'",
+ "postlint": "npm-template-check",
+ "lintfix": "npm run lint -- --fix",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "prepublishOnly": "git push origin --follow-tags",
+ "snap": "tap",
+ "posttest": "npm run lint"
+ },
+ "tap": {
+ "check-coverage": true
+ },
+ "repository": "https://github.com/npm/libnpmhook",
+ "keywords": [
+ "npm",
+ "hooks",
+ "registry",
+ "npm api"
+ ],
+ "author": "GitHub Inc.",
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^2.0.0",
+ "npm-registry-fetch": "^11.0.0"
+ },
+ "devDependencies": {
+ "nock": "^9.6.1",
+ "tap": "^15.1.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16"
+ },
+ "templateOSS": {
+ "version": "2.4.1"
+ }
+}
diff --git a/workspaces/libnpmhook/test/fixtures/tnock.js b/workspaces/libnpmhook/test/fixtures/tnock.js
new file mode 100644
index 000000000..048639a50
--- /dev/null
+++ b/workspaces/libnpmhook/test/fixtures/tnock.js
@@ -0,0 +1,12 @@
+'use strict'
+
+const nock = require('nock')
+
+module.exports = tnock
+function tnock (t, host) {
+ const server = nock(host)
+ t.teardown(function () {
+ server.done()
+ })
+ return server
+}
diff --git a/workspaces/libnpmhook/test/index.js b/workspaces/libnpmhook/test/index.js
new file mode 100644
index 000000000..7ca3b06ae
--- /dev/null
+++ b/workspaces/libnpmhook/test/index.js
@@ -0,0 +1,267 @@
+'use strict'
+
+const test = require('tap').test
+const tnock = require('./fixtures/tnock.js')
+
+const hooks = require('../lib/index.js')
+
+const OPTS = {
+ registry: 'https://mock.reg/',
+}
+
+const HOOK_URL = 'https://my.hook.url/'
+const REG = 'https://registry.npmjs.org/'
+
+test('add package hook with no options', t => {
+ const params = {
+ type: 'package',
+ name: 'mypkg',
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }
+ const hook = Object.assign({
+ id: 'deadbeef',
+ status: 'active',
+ }, params)
+ tnock(t, REG)
+ .post('/-/npm/v1/hooks/hook', params)
+ .reply(200, hook)
+ return hooks.add('mypkg', HOOK_URL, 'sekrit')
+ .then(json => t.same(json, hook))
+})
+
+test('add package hook', t => {
+ const params = {
+ type: 'package',
+ name: 'mypkg',
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }
+ const hook = Object.assign({
+ id: 'deadbeef',
+ status: 'active',
+ }, params)
+ tnock(t, OPTS.registry)
+ .post('/-/npm/v1/hooks/hook', params)
+ .reply(200, hook)
+ return hooks.add('mypkg', HOOK_URL, 'sekrit', OPTS)
+ .then(json => t.same(json, hook))
+})
+
+test('add scoped package hook', t => {
+ const params = {
+ type: 'package',
+ name: '@myscope/mypkg',
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }
+ const hook = Object.assign({
+ id: 'deadbeef',
+ status: 'active',
+ }, params)
+ tnock(t, OPTS.registry)
+ .post('/-/npm/v1/hooks/hook', params)
+ .reply(200, hook)
+ return hooks.add('@myscope/mypkg', HOOK_URL, 'sekrit', OPTS)
+ .then(json => t.same(json, hook))
+})
+
+test('add owner hook', t => {
+ const params = {
+ type: 'owner',
+ name: 'myuser',
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }
+ const hook = Object.assign({
+ id: 'deadbeef',
+ status: 'active',
+ }, params)
+ tnock(t, OPTS.registry)
+ .post('/-/npm/v1/hooks/hook', params)
+ .reply(200, hook)
+ return hooks.add('~myuser', HOOK_URL, 'sekrit', OPTS)
+ .then(json => t.same(json, hook))
+})
+
+test('add scope hook', t => {
+ const params = {
+ type: 'scope',
+ name: '@myscope',
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }
+ const hook = Object.assign({
+ id: 'deadbeef',
+ status: 'active',
+ }, params)
+ tnock(t, OPTS.registry)
+ .post('/-/npm/v1/hooks/hook', params)
+ .reply(200, hook)
+ return hooks.add('@myscope', HOOK_URL, 'sekrit', OPTS)
+ .then(json => t.same(json, hook))
+})
+
+test('rm with no options', t => {
+ tnock(t, REG)
+ .delete('/-/npm/v1/hooks/hook/hithere')
+ .reply(200, { id: 'hithere' })
+ return hooks.rm('hithere')
+ .then(json => t.equal(json.id, 'hithere'))
+})
+
+test('rm', t => {
+ tnock(t, OPTS.registry)
+ .delete('/-/npm/v1/hooks/hook/hithere')
+ .reply(200, { id: 'hithere' })
+ return hooks.rm('hithere', OPTS)
+ .then(json => t.equal(json.id, 'hithere'))
+})
+
+test('rm null on 404', t => {
+ tnock(t, OPTS.registry)
+ .delete('/-/npm/v1/hooks/hook/hithere')
+ .reply(404)
+ return hooks.rm('hithere', OPTS)
+ .then(json => t.equal(json, null))
+})
+
+test('rm null on other err', t => {
+ tnock(t, OPTS.registry)
+ .delete('/-/npm/v1/hooks/hook/hithere')
+ .reply(401)
+ return hooks.rm('hithere', OPTS).then(
+ () => {
+ throw new Error('should not succees')
+ },
+ err => t.equal(err.code, 'E401', 'got a proper error + code')
+ )
+})
+
+test('find with no options', t => {
+ tnock(t, REG)
+ .get('/-/npm/v1/hooks/hook/hithere')
+ .reply(200, { id: 'hithere' })
+ return hooks.find('hithere')
+ .then(json => t.equal(json.id, 'hithere'))
+})
+
+test('find', t => {
+ tnock(t, OPTS.registry)
+ .get('/-/npm/v1/hooks/hook/hithere')
+ .reply(200, { id: 'hithere' })
+ return hooks.find('hithere', OPTS)
+ .then(json => t.equal(json.id, 'hithere'))
+})
+
+test('ls', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, REG)
+ .get('/-/npm/v1/hooks')
+ .reply(200, { objects: entries })
+ return hooks.ls().then(
+ json => t.same(json, entries)
+ )
+})
+
+test('ls.stream', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, REG)
+ .get('/-/npm/v1/hooks')
+ .reply(200, { objects: entries })
+
+ return hooks.ls.stream().collect().then(
+ json => t.same(json, entries)
+ )
+})
+
+test('ls', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, OPTS.registry)
+ .get('/-/npm/v1/hooks')
+ .reply(200, { objects: entries })
+ return hooks.ls(OPTS).then(
+ json => t.same(json, entries)
+ )
+})
+
+test('ls package', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, OPTS.registry)
+ .get('/-/npm/v1/hooks?package=%40npm%2Fhooks')
+ .reply(200, { objects: entries })
+ return hooks.ls({
+ ...OPTS,
+ package: '@npm/hooks',
+ }).then(json => t.same(json, entries))
+})
+
+test('ls limit+offset', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, OPTS.registry)
+ .get('/-/npm/v1/hooks?limit=10&offset=20')
+ .reply(200, { objects: entries })
+ return hooks.ls({
+ ...OPTS,
+ limit: 10,
+ offset: 20,
+ }).then(json => t.same(json, entries))
+})
+
+test('ls package+limit+offset', t => {
+ const entries = [
+ { id: 'first' },
+ { id: 'second' },
+ { id: 'third' },
+ ]
+ tnock(t, OPTS.registry)
+ .get('/-/npm/v1/hooks?package=%40npm%2Fhooks&limit=10&offset=20')
+ .reply(200, { objects: entries })
+ return hooks.ls({
+ ...OPTS,
+ limit: 10,
+ offset: 20,
+ package: '@npm/hooks',
+ }).then(json => t.same(json, entries))
+})
+test('update with no options', t => {
+ tnock(t, REG)
+ .put('/-/npm/v1/hooks/hook/hi')
+ .reply(200, (uri, body) => body)
+ return hooks.update('hi', HOOK_URL, 'sekrit')
+ .then(json => t.same(json, {
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }))
+})
+
+test('update', t => {
+ tnock(t, OPTS.registry)
+ .put('/-/npm/v1/hooks/hook/hi')
+ .reply(200, (uri, body) => body)
+ return hooks.update('hi', HOOK_URL, 'sekrit', OPTS)
+ .then(json => t.same(json, {
+ endpoint: HOOK_URL,
+ secret: 'sekrit',
+ }))
+})