libnpmaccess
Advanced tools
Comparing version 3.0.2 to 4.0.0
# Change Log | ||
<a name="4.0.0"></a> | ||
## [4.0.0](https://github.com/npm/libnpmaccess/compare/v3.0.2...v4.0.0) (2020-03-02) | ||
### BREAKING CHANGES | ||
- `25ac61b` fix: remove figgy-pudding ([@claudiahdz](https://github.com/claudiahdz)) | ||
- `8d6f692` chore: rename opts.mapJson to opts.mapJSON ([@mikemimik](https://github.com/mikemimik)) | ||
### Features | ||
- `257879a` chore: removed standard-version as a dep; updated scripts for version/publishing ([@mikemimik](https://github.com/mikemimik)) | ||
- `46c6740` fix: pull-request feedback; read full commit message ([@mikemimik](https://github.com/mikemimik)) | ||
- `778c102` chore: updated test, made case more clear ([@mikemimik](https://github.com/mikemimik)) | ||
- `6dc9852` fix: refactored 'pwrap' function out of code base; use native promises ([@mikemimik](https://github.com/mikemimik)) | ||
- `d2e7219` chore: updated package scripts; update CI workflow ([@mikemimik](https://github.com/mikemimik)) | ||
- `5872364` chore: renamed test/util/ to test/fixture/; tap will ignore now ([@mikemimik](https://github.com/mikemimik)) | ||
- `3c6b71d` chore: linted test file; made tap usage 'better' ([@mikemimik](https://github.com/mikemimik)) | ||
- `20f0858` fix: added default values to params for API functions (with tests) ([@mikemimik](https://github.com/mikemimik)) | ||
- `3218289` feat: replace get-stream with minipass ([@mikemimik](https://github.com/mikemimik)) | ||
### Documentation | ||
- `6c8ffa0` docs: removed opts.Promise from docs; no longer in use ([@mikemimik](https://github.com/mikemimik)) | ||
- `311bff5` chore: added return types to function docs in README ([@mikemimik](https://github.com/mikemimik)) | ||
- `823726a` chore: removed travis badge, added github actions badge ([@mikemimik](https://github.com/mikemimik)) | ||
- `80e80ac` chore: updated README ([@mikemimik](https://github.com/mikemimik)) | ||
### Dependencies | ||
- `baed2b9` deps: standard-version@7.1.0 (audit fix) ([@mikemimik](https://github.com/mikemimik)) | ||
- `65c2204` deps: nock@12.0.1 (audit fix) ([@mikemimik](https://github.com/mikemimik)) | ||
- `2668386` deps: npm-registry-fetch@8.0.0 ([@mikemimik](https://github.com/mikemimik)) | ||
- `ef093e2` deps: tap@14.10.6 ([@mikemimik](https://github.com/mikemimik)) | ||
### Miscellanieous | ||
- `8e33902` chore: basic project updates ([@claudiahdz](https://github.com/claudiahdz)) | ||
- `50e1433` fix: update return value; add tests ([@mikemimik](https://github.com/mikemimik)) | ||
- `36d5c80` chore: updated gitignore; includes coverage folder ([@mikemimik](https://github.com/mikemimik)) | ||
--- | ||
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. | ||
@@ -4,0 +41,0 @@ |
201
index.js
'use strict' | ||
const figgyPudding = require('figgy-pudding') | ||
const getStream = require('get-stream') | ||
const Minipass = require('minipass') | ||
const npa = require('npm-package-arg') | ||
const npmFetch = require('npm-registry-fetch') | ||
const {PassThrough} = require('stream') | ||
const validate = require('aproba') | ||
const AccessConfig = figgyPudding({ | ||
Promise: {default: () => Promise} | ||
}) | ||
const eu = encodeURIComponent | ||
@@ -22,2 +16,11 @@ const npar = spec => { | ||
} | ||
const mapJSON = (value, [key]) => { | ||
if (value === 'read') { | ||
return [key, 'read-only'] | ||
} else if (value === 'write') { | ||
return [key, 'read-write'] | ||
} else { | ||
return [key, value] | ||
} | ||
} | ||
@@ -28,21 +31,20 @@ const cmd = module.exports = {} | ||
cmd.restricted = (spec, opts) => setAccess(spec, 'restricted', opts) | ||
function setAccess (spec, access, opts) { | ||
opts = AccessConfig(opts) | ||
return pwrap(opts, () => { | ||
function setAccess (spec, access, opts = {}) { | ||
return Promise.resolve().then(() => { | ||
spec = npar(spec) | ||
validate('OSO', [spec, access, opts]) | ||
const uri = `/-/package/${eu(spec.name)}/access` | ||
return npmFetch(uri, opts.concat({ | ||
return npmFetch(uri, { | ||
...opts, | ||
method: 'POST', | ||
body: {access}, | ||
body: { access }, | ||
spec | ||
})) | ||
}).then(res => res.body.resume() && true) | ||
}).then(() => true) | ||
}) | ||
} | ||
cmd.grant = (spec, entity, permissions, opts) => { | ||
opts = AccessConfig(opts) | ||
return pwrap(opts, () => { | ||
cmd.grant = (spec, entity, permissions, opts = {}) => { | ||
return Promise.resolve().then(() => { | ||
spec = npar(spec) | ||
const {scope, team} = splitEntity(entity) | ||
const { scope, team } = splitEntity(entity) | ||
validate('OSSSO', [spec, scope, team, permissions, opts]) | ||
@@ -53,48 +55,49 @@ if (permissions !== 'read-write' && permissions !== 'read-only') { | ||
const uri = `/-/team/${eu(scope)}/${eu(team)}/package` | ||
return npmFetch(uri, opts.concat({ | ||
return npmFetch(uri, { | ||
...opts, | ||
method: 'PUT', | ||
body: {package: spec.name, permissions}, | ||
body: { package: spec.name, permissions }, | ||
scope, | ||
spec, | ||
ignoreBody: true | ||
})) | ||
}).then(() => true) | ||
}) | ||
.then(() => true) | ||
}) | ||
} | ||
cmd.revoke = (spec, entity, opts) => { | ||
opts = AccessConfig(opts) | ||
return pwrap(opts, () => { | ||
cmd.revoke = (spec, entity, opts = {}) => { | ||
return Promise.resolve().then(() => { | ||
spec = npar(spec) | ||
const {scope, team} = splitEntity(entity) | ||
const { scope, team } = splitEntity(entity) | ||
validate('OSSO', [spec, scope, team, opts]) | ||
const uri = `/-/team/${eu(scope)}/${eu(team)}/package` | ||
return npmFetch(uri, opts.concat({ | ||
return npmFetch(uri, { | ||
...opts, | ||
method: 'DELETE', | ||
body: {package: spec.name}, | ||
body: { package: spec.name }, | ||
scope, | ||
spec, | ||
ignoreBody: true | ||
})) | ||
}).then(() => true) | ||
}) | ||
.then(() => true) | ||
}) | ||
} | ||
cmd.lsPackages = (entity, opts) => { | ||
opts = AccessConfig(opts) | ||
return pwrap(opts, () => { | ||
return getStream.array( | ||
cmd.lsPackages.stream(entity, opts) | ||
).then(data => data.reduce((acc, [key, val]) => { | ||
if (!acc) { | ||
acc = {} | ||
} | ||
acc[key] = val | ||
return acc | ||
}, null)) | ||
}) | ||
return cmd.lsPackages.stream(entity, opts) | ||
.collect() | ||
.then(data => { | ||
return data.reduce((acc, [key, val]) => { | ||
if (!acc) { | ||
acc = {} | ||
} | ||
acc[key] = val | ||
return acc | ||
}, null) | ||
}) | ||
} | ||
cmd.lsPackages.stream = (entity, opts) => { | ||
cmd.lsPackages.stream = (entity, opts = {}) => { | ||
validate('SO|SZ', [entity, opts]) | ||
opts = AccessConfig(opts) | ||
const {scope, team} = splitEntity(entity) | ||
const { scope, team } = splitEntity(entity) | ||
let uri | ||
@@ -106,25 +109,20 @@ if (team) { | ||
} | ||
opts = opts.concat({ | ||
query: {format: 'cli'}, | ||
mapJson (value, [key]) { | ||
if (value === 'read') { | ||
return [key, 'read-only'] | ||
} else if (value === 'write') { | ||
return [key, 'read-write'] | ||
const nextOpts = { | ||
...opts, | ||
query: { format: 'cli' }, | ||
mapJSON | ||
} | ||
const ret = new Minipass({ objectMode: true }) | ||
npmFetch.json.stream(uri, '*', nextOpts) | ||
.on('error', err => { | ||
if (err.code === 'E404' && !team) { | ||
uri = `/-/user/${eu(scope)}/package` | ||
npmFetch.json.stream(uri, '*', nextOpts) | ||
.on('error', err => ret.emit('error', err)) | ||
.pipe(ret) | ||
} else { | ||
return [key, value] | ||
ret.emit('error', err) | ||
} | ||
} | ||
}) | ||
const ret = new PassThrough({objectMode: true}) | ||
npmFetch.json.stream(uri, '*', opts).on('error', err => { | ||
if (err.code === 'E404' && !team) { | ||
uri = `/-/user/${eu(scope)}/package` | ||
npmFetch.json.stream(uri, '*', opts).on( | ||
'error', err => ret.emit('error', err) | ||
).pipe(ret) | ||
} else { | ||
ret.emit('error', err) | ||
} | ||
}).pipe(ret) | ||
}) | ||
.pipe(ret) | ||
return ret | ||
@@ -134,17 +132,14 @@ } | ||
cmd.lsCollaborators = (spec, user, opts) => { | ||
if (typeof user === 'object' && !opts) { | ||
opts = user | ||
user = undefined | ||
} | ||
opts = AccessConfig(opts) | ||
return pwrap(opts, () => { | ||
return getStream.array( | ||
cmd.lsCollaborators.stream(spec, user, opts) | ||
).then(data => data.reduce((acc, [key, val]) => { | ||
if (!acc) { | ||
acc = {} | ||
} | ||
acc[key] = val | ||
return acc | ||
}, null)) | ||
return Promise.resolve().then(() => { | ||
return cmd.lsCollaborators.stream(spec, user, opts) | ||
.collect() | ||
.then(data => { | ||
return data.reduce((acc, [key, val]) => { | ||
if (!acc) { | ||
acc = {} | ||
} | ||
acc[key] = val | ||
return acc | ||
}, null) | ||
}) | ||
}) | ||
@@ -157,19 +152,13 @@ } | ||
user = undefined | ||
} else if (!opts) { | ||
opts = {} | ||
} | ||
opts = AccessConfig(opts) | ||
spec = npar(spec) | ||
validate('OSO|OZO', [spec, user, opts]) | ||
const uri = `/-/package/${eu(spec.name)}/collaborators` | ||
return npmFetch.json.stream(uri, '*', opts.concat({ | ||
query: {format: 'cli', user: user || undefined}, | ||
mapJson (value, [key]) { | ||
if (value === 'read') { | ||
return [key, 'read-only'] | ||
} else if (value === 'write') { | ||
return [key, 'read-write'] | ||
} else { | ||
return [key, value] | ||
} | ||
} | ||
})) | ||
return npmFetch.json.stream(uri, '*', { | ||
...opts, | ||
query: { format: 'cli', user: user || undefined }, | ||
mapJSON | ||
}) | ||
} | ||
@@ -179,15 +168,15 @@ | ||
cmd.tfaNotRequired = (spec, opts) => setRequires2fa(spec, false, opts) | ||
function setRequires2fa (spec, required, opts) { | ||
opts = AccessConfig(opts) | ||
return new opts.Promise((resolve, reject) => { | ||
function setRequires2fa (spec, required, opts = {}) { | ||
return Promise.resolve().then(() => { | ||
spec = npar(spec) | ||
validate('OBO', [spec, required, opts]) | ||
const uri = `/-/package/${eu(spec.name)}/access` | ||
return npmFetch(uri, opts.concat({ | ||
return npmFetch(uri, { | ||
...opts, | ||
method: 'POST', | ||
body: {publish_requires_tfa: required}, | ||
body: { publish_requires_tfa: required }, | ||
spec, | ||
ignoreBody: true | ||
})).then(resolve, reject) | ||
}).then(() => true) | ||
}).then(() => true) | ||
}) | ||
} | ||
@@ -200,10 +189,4 @@ | ||
function splitEntity (entity = '') { | ||
let [, scope, team] = entity.match(/^@?([^:]+)(?::(.*))?$/) || [] | ||
return {scope, team} | ||
const [, scope, team] = entity.match(/^@?([^:]+)(?::(.*))?$/) || [] | ||
return { scope, team } | ||
} | ||
function pwrap (opts, fn) { | ||
return new opts.Promise((resolve, reject) => { | ||
fn().then(resolve, reject) | ||
}) | ||
} |
{ | ||
"name": "libnpmaccess", | ||
"version": "3.0.2", | ||
"version": "4.0.0", | ||
"description": "programmatic library for `npm access` commands", | ||
"author": { | ||
"name": "Kat Marchán", | ||
"email": "kzm@zkat.tech", | ||
"twitter": "maybekatz" | ||
}, | ||
"author": "Kat Marchán <kzm@sykosomatic.org>", | ||
"license": "ISC", | ||
"scripts": { | ||
"prerelease": "npm t", | ||
"release": "standard-version -s", | ||
"postrelease": "npm publish && git push --follow-tags", | ||
"pretest": "standard", | ||
"test": "tap -J --100 test/*.js", | ||
"update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'", | ||
"update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'" | ||
"preversion": "npm test", | ||
"postversion": "npm publish", | ||
"postpublish": "git push origin --follow-tags", | ||
"lint": "standard", | ||
"test": "tap" | ||
}, | ||
"devDependencies": { | ||
"nock": "^9.6.1", | ||
"standard": "*", | ||
"standard-version": "*", | ||
"tap": "*", | ||
"weallbehave": "*", | ||
"weallcontribute": "*" | ||
"nock": "^12.0.1", | ||
"standard": "^14.3.0", | ||
"tap": "^14.10.6" | ||
}, | ||
@@ -36,6 +27,12 @@ "repository": { | ||
"aproba": "^2.0.0", | ||
"get-stream": "^4.0.0", | ||
"npm-package-arg": "^6.1.0", | ||
"npm-registry-fetch": "^4.0.0" | ||
"minipass": "^3.1.1", | ||
"npm-package-arg": "^8.0.0", | ||
"npm-registry-fetch": "^8.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=10" | ||
}, | ||
"tap": { | ||
"check-coverage": true | ||
} | ||
} |
@@ -1,3 +0,8 @@ | ||
# libnpmaccess [![npm version](https://img.shields.io/npm/v/libnpmaccess.svg)](https://npm.im/libnpmaccess) [![license](https://img.shields.io/npm/l/libnpmaccess.svg)](https://npm.im/libnpmaccess) [![Travis](https://img.shields.io/travis/npm/libnpmaccess/latest.svg)](https://travis-ci.org/npm/libnpmaccess) [![AppVeyor](https://img.shields.io/appveyor/ci/zkat/libnpmaccess/latest.svg)](https://ci.appveyor.com/project/zkat/libnpmaccess) [![Coverage Status](https://coveralls.io/repos/github/npm/libnpmaccess/badge.svg?branch=latest)](https://coveralls.io/github/npm/libnpmaccess?branch=latest) | ||
# libnpmaccess | ||
[![npm version](https://img.shields.io/npm/v/libnpmaccess.svg)](https://npm.im/libnpmaccess) | ||
[![license](https://img.shields.io/npm/l/libnpmaccess.svg)](https://npm.im/libnpmaccess) | ||
[![GitHub Actions](https://github.com/npm/libnpmaccess/workflows/Node%20CI/badge.svg)](https://github.com/npm/libnpmaccess/actions?query=workflow%3A%22Node+CI%22) | ||
[![Coverage Status](https://coveralls.io/repos/github/npm/libnpmaccess/badge.svg?branch=latest)](https://coveralls.io/github/npm/libnpmaccess?branch=latest) | ||
[`libnpmaccess`](https://github.com/npm/libnpmaccess) is a Node.js | ||
@@ -40,17 +45,2 @@ library that provides programmatic access to the guts of the npm CLI's `npm | ||
### Contributing | ||
The npm team enthusiastically welcomes contributions and project participation! | ||
There's a bunch of things you can do if you want to contribute! The [Contributor | ||
Guide](CONTRIBUTING.md) has all the information you need for everything from | ||
reporting bugs to contributing entire new features. Please don't hesitate to | ||
jump in if you'd like to, or even ask us questions if something isn't clear. | ||
All participants and maintainers in this project are expected to follow [Code of | ||
Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other. | ||
Please refer to the [Changelog](CHANGELOG.md) for project history details, too. | ||
Happy hacking! | ||
### API | ||
@@ -70,5 +60,4 @@ | ||
* `opts.otp` - certain operations will require an OTP token to be passed in. If a `libnpmaccess` command fails with `err.code === EOTP`, please retry the request with `{otp: <2fa token>}` | ||
* `opts.Promise` - If you pass this in, the Promises returned by `libnpmaccess` commands will use this Promise class instead. For example: `{Promise: require('bluebird')}` | ||
#### <a name="public"></a> `> access.public(spec, [opts]) -> Promise` | ||
#### <a name="public"></a> `> access.public(spec, [opts]) -> Promise<Boolean>` | ||
@@ -87,3 +76,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="restricted"></a> `> access.restricted(spec, [opts]) -> Promise` | ||
#### <a name="restricted"></a> `> access.restricted(spec, [opts]) -> Promise<Boolean>` | ||
@@ -102,3 +91,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="grant"></a> `> access.grant(spec, team, permissions, [opts]) -> Promise` | ||
#### <a name="grant"></a> `> access.grant(spec, team, permissions, [opts]) -> Promise<Boolean>` | ||
@@ -121,3 +110,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="revoke"></a> `> access.revoke(spec, team, [opts]) -> Promise` | ||
#### <a name="revoke"></a> `> access.revoke(spec, team, [opts]) -> Promise<Boolean>` | ||
@@ -140,3 +129,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="tfa-required"></a> `> access.tfaRequired(spec, [opts]) -> Promise` | ||
#### <a name="tfa-required"></a> `> access.tfaRequired(spec, [opts]) -> Promise<Boolean>` | ||
@@ -156,3 +145,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="tfa-not-required"></a> `> access.tfaNotRequired(spec, [opts]) -> Promise` | ||
#### <a name="tfa-not-required"></a> `> access.tfaNotRequired(spec, [opts]) -> Promise<Boolean>` | ||
@@ -173,3 +162,3 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible | ||
#### <a name="ls-packages"></a> `> access.lsPackages(entity, [opts]) -> Promise` | ||
#### <a name="ls-packages"></a> `> access.lsPackages(entity, [opts]) -> Promise<Object | null>` | ||
@@ -224,3 +213,3 @@ `entity` must be either a valid org or user name, or a fully-qualified team name | ||
#### <a name="ls-collaborators"></a> `> access.lsCollaborators(spec, [user], [opts]) -> Promise` | ||
#### <a name="ls-collaborators"></a> `> access.lsCollaborators(spec, [user], [opts]) -> Promise<Object | null>` | ||
@@ -227,0 +216,0 @@ `spec` must be an [`npm-package-arg`](https://npm.im/npm-package-arg)-compatible |
'use strict' | ||
const figgyPudding = require('figgy-pudding') | ||
const getStream = require('get-stream') | ||
const {test} = require('tap') | ||
const tnock = require('./util/tnock.js') | ||
const t = require('tap') | ||
const tnock = require('./fixtures/tnock.js') | ||
@@ -11,9 +9,9 @@ const access = require('../index.js') | ||
const REG = 'http://localhost:1337' | ||
const OPTS = figgyPudding({})({ | ||
const OPTS = { | ||
registry: REG | ||
}) | ||
} | ||
test('access public', t => { | ||
t.test('access public', t => { | ||
tnock(t, REG).post( | ||
'/-/package/%40foo%2Fbar/access', {access: 'public'} | ||
'/-/package/%40foo%2Fbar/access', { access: 'public' } | ||
).reply(200) | ||
@@ -25,5 +23,15 @@ return access.public('@foo/bar', OPTS).then(ret => { | ||
test('access restricted', t => { | ||
t.test('access public - failure', t => { | ||
tnock(t, REG).post( | ||
'/-/package/%40foo%2Fbar/access', {access: 'restricted'} | ||
'/-/package/%40foo%2Fbar/access', { access: 'public' } | ||
).reply(418) | ||
return access.public('@foo/bar', OPTS) | ||
.catch(err => { | ||
t.equals(err.statusCode, 418, 'fails with code from registry') | ||
}) | ||
}) | ||
t.test('access restricted', t => { | ||
tnock(t, REG).post( | ||
'/-/package/%40foo%2Fbar/access', { access: 'restricted' } | ||
).reply(200) | ||
@@ -35,6 +43,16 @@ return access.restricted('@foo/bar', OPTS).then(ret => { | ||
test('access 2fa-required', t => { | ||
t.test('access restricted - failure', t => { | ||
tnock(t, REG).post( | ||
'/-/package/%40foo%2Fbar/access', { access: 'restricted' } | ||
).reply(418) | ||
return access.restricted('@foo/bar', OPTS) | ||
.catch(err => { | ||
t.equals(err.statusCode, 418, 'fails with code from registry') | ||
}) | ||
}) | ||
t.test('access 2fa-required', t => { | ||
tnock(t, REG).post('/-/package/%40foo%2Fbar/access', { | ||
publish_requires_tfa: true | ||
}).reply(200, {ok: true}) | ||
}).reply(200, { ok: true }) | ||
return access.tfaRequired('@foo/bar', OPTS).then(ret => { | ||
@@ -45,6 +63,6 @@ t.deepEqual(ret, true, 'request succeeded') | ||
test('access 2fa-not-required', t => { | ||
t.test('access 2fa-not-required', t => { | ||
tnock(t, REG).post('/-/package/%40foo%2Fbar/access', { | ||
publish_requires_tfa: false | ||
}).reply(200, {ok: true}) | ||
}).reply(200, { ok: true }) | ||
return access.tfaNotRequired('@foo/bar', OPTS).then(ret => { | ||
@@ -55,3 +73,3 @@ t.deepEqual(ret, true, 'request succeeded') | ||
test('access grant basic read-write', t => { | ||
t.test('access grant basic read-write', t => { | ||
tnock(t, REG).put('/-/team/myorg/myteam/package', { | ||
@@ -68,3 +86,3 @@ package: '@foo/bar', | ||
test('access grant basic read-only', t => { | ||
t.test('access grant basic read-only', t => { | ||
tnock(t, REG).put('/-/team/myorg/myteam/package', { | ||
@@ -81,3 +99,3 @@ package: '@foo/bar', | ||
test('access grant bad perm', t => { | ||
t.test('access grant bad perm', t => { | ||
return access.grant( | ||
@@ -96,3 +114,3 @@ '@foo/bar', 'myorg:myteam', 'unknown', OPTS | ||
test('access grant no entity', t => { | ||
t.test('access grant no entity', t => { | ||
return access.grant( | ||
@@ -111,3 +129,3 @@ '@foo/bar', undefined, 'read-write', OPTS | ||
test('access grant basic unscoped', t => { | ||
t.test('access grant basic unscoped', t => { | ||
tnock(t, REG).put('/-/team/myorg/myteam/package', { | ||
@@ -124,3 +142,18 @@ package: 'bar', | ||
test('access revoke basic', t => { | ||
t.test('access grant no opts passed', t => { | ||
// NOTE: mocking real url, because no opts variable means `registry` value | ||
// will be defauled to real registry url | ||
tnock(t, 'https://registry.npmjs.org') | ||
.put('/-/team/myorg/myteam/package', { | ||
package: 'bar', | ||
permissions: 'read-write' | ||
}) | ||
.reply(201) | ||
return access.grant('bar', 'myorg:myteam', 'read-write') | ||
.then(ret => { | ||
t.equals(ret, true, 'request succeeded') | ||
}) | ||
}) | ||
t.test('access revoke basic', t => { | ||
tnock(t, REG).delete('/-/team/myorg/myteam/package', { | ||
@@ -134,6 +167,6 @@ package: '@foo/bar' | ||
test('access revoke basic unscoped', t => { | ||
t.test('access revoke basic unscoped', t => { | ||
tnock(t, REG).delete('/-/team/myorg/myteam/package', { | ||
package: 'bar' | ||
}).reply(200, {accessChanged: true}) | ||
}).reply(200, { accessChanged: true }) | ||
return access.revoke('bar', 'myorg:myteam', OPTS).then(ret => { | ||
@@ -144,3 +177,17 @@ t.deepEqual(ret, true, 'request succeeded') | ||
test('ls-packages on team', t => { | ||
t.test('access revoke no opts passed', t => { | ||
// NOTE: mocking real url, because no opts variable means `registry` value | ||
// will be defauled to real registry url | ||
tnock(t, 'https://registry.npmjs.org') | ||
.delete('/-/team/myorg/myteam/package', { | ||
package: 'bar' | ||
}) | ||
.reply(201) | ||
return access.revoke('bar', 'myorg:myteam') | ||
.then(ret => { | ||
t.equals(ret, true, 'request succeeded') | ||
}) | ||
}) | ||
t.test('ls-packages on team', t => { | ||
const serverPackages = { | ||
@@ -164,3 +211,3 @@ '@foo/bar': 'write', | ||
test('ls-packages on org', t => { | ||
t.test('ls-packages on org', t => { | ||
const serverPackages = { | ||
@@ -184,3 +231,3 @@ '@foo/bar': 'write', | ||
test('ls-packages on user', t => { | ||
t.test('ls-packages on user', t => { | ||
const serverPackages = { | ||
@@ -197,3 +244,3 @@ '@foo/bar': 'write', | ||
const srv = tnock(t, REG) | ||
srv.get('/-/org/myuser/package?format=cli').reply(404, {error: 'not found'}) | ||
srv.get('/-/org/myuser/package?format=cli').reply(404, { error: 'not found' }) | ||
srv.get('/-/user/myuser/package?format=cli').reply(200, serverPackages) | ||
@@ -205,3 +252,3 @@ return access.lsPackages('myuser', OPTS).then(data => { | ||
test('ls-packages error on team', t => { | ||
t.test('ls-packages error on team', t => { | ||
tnock(t, REG).get('/-/team/myorg/myteam/package?format=cli').reply(404) | ||
@@ -214,6 +261,6 @@ return access.lsPackages('myorg:myteam', OPTS).then( | ||
test('ls-packages error on user', t => { | ||
t.test('ls-packages error on user', t => { | ||
const srv = tnock(t, REG) | ||
srv.get('/-/org/myuser/package?format=cli').reply(404, {error: 'not found'}) | ||
srv.get('/-/user/myuser/package?format=cli').reply(404, {error: 'not found'}) | ||
srv.get('/-/org/myuser/package?format=cli').reply(404, { error: 'not found' }) | ||
srv.get('/-/user/myuser/package?format=cli').reply(404, { error: 'not found' }) | ||
return access.lsPackages('myuser', OPTS).then( | ||
@@ -225,3 +272,3 @@ () => { throw new Error('should not have succeeded') }, | ||
test('ls-packages bad response', t => { | ||
t.test('ls-packages bad response', t => { | ||
tnock(t, REG).get( | ||
@@ -235,3 +282,3 @@ '/-/team/myorg/myteam/package?format=cli' | ||
test('ls-packages stream', t => { | ||
t.test('ls-packages stream', t => { | ||
const serverPackages = { | ||
@@ -250,10 +297,33 @@ '@foo/bar': 'write', | ||
).reply(200, serverPackages) | ||
return getStream.array( | ||
access.lsPackages.stream('myorg:myteam', OPTS) | ||
).then(data => { | ||
t.deepEqual(data, clientPackages, 'got streamed client package info') | ||
}) | ||
return access.lsPackages.stream('myorg:myteam', OPTS) | ||
.collect() | ||
.then(data => { | ||
t.deepEqual(data, clientPackages, 'got streamed client package info') | ||
}) | ||
}) | ||
test('ls-collaborators', t => { | ||
t.test('ls-packages stream no opts', t => { | ||
const serverPackages = { | ||
'@foo/bar': 'write', | ||
'@foo/util': 'read', | ||
'@foo/other': 'shrödinger' | ||
} | ||
const clientPackages = [ | ||
['@foo/bar', 'read-write'], | ||
['@foo/util', 'read-only'], | ||
['@foo/other', 'shrödinger'] | ||
] | ||
// NOTE: mocking real url, because no opts variable means `registry` value | ||
// will be defauled to real registry url | ||
tnock(t, 'https://registry.npmjs.org') | ||
.get('/-/team/myorg/myteam/package?format=cli') | ||
.reply(200, serverPackages) | ||
return access.lsPackages.stream('myorg:myteam') | ||
.collect() | ||
.then(data => { | ||
t.deepEqual(data, clientPackages, 'got streamed client package info') | ||
}) | ||
}) | ||
t.test('ls-collaborators', t => { | ||
const serverCollaborators = { | ||
@@ -277,3 +347,3 @@ 'myorg:myteam': 'write', | ||
test('ls-collaborators stream', t => { | ||
t.test('ls-collaborators stream', t => { | ||
const serverCollaborators = { | ||
@@ -292,10 +362,10 @@ 'myorg:myteam': 'write', | ||
).reply(200, serverCollaborators) | ||
return getStream.array( | ||
access.lsCollaborators.stream('@foo/bar', OPTS) | ||
).then(data => { | ||
t.deepEqual(data, clientCollaborators, 'got collaborators') | ||
}) | ||
return access.lsCollaborators.stream('@foo/bar', OPTS) | ||
.collect() | ||
.then(data => { | ||
t.deepEqual(data, clientCollaborators, 'got collaborators') | ||
}) | ||
}) | ||
test('ls-collaborators w/scope', t => { | ||
t.test('ls-collaborators w/scope', t => { | ||
const serverCollaborators = { | ||
@@ -319,3 +389,3 @@ 'myorg:myteam': 'write', | ||
test('ls-collaborators w/o scope', t => { | ||
t.test('ls-collaborators w/o scope', t => { | ||
const serverCollaborators = { | ||
@@ -339,3 +409,3 @@ 'myorg:myteam': 'write', | ||
test('ls-collaborators bad response', t => { | ||
t.test('ls-collaborators bad response', t => { | ||
tnock(t, REG).get( | ||
@@ -349,3 +419,3 @@ '/-/package/%40foo%2Fbar/collaborators?format=cli' | ||
test('error on non-registry specs', t => { | ||
t.test('error on non-registry specs', t => { | ||
const resolve = () => { throw new Error('should not succeed') } | ||
@@ -356,3 +426,3 @@ const reject = err => t.match( | ||
return Promise.all([ | ||
access.public('foo/bar').then(resolve, reject), | ||
access.public('githubusername/reponame').then(resolve, reject), | ||
access.restricted('foo/bar').then(resolve, reject), | ||
@@ -367,3 +437,3 @@ access.grant('foo/bar', 'myorg', 'myteam', 'read-only').then(resolve, reject), | ||
test('edit', t => { | ||
t.test('edit', t => { | ||
t.equal(typeof access.edit, 'function', 'access.edit exists') | ||
@@ -370,0 +440,0 @@ t.throws(() => { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
3
565
37546
9
248
+ Addedminipass@^3.1.1
+ Added@gar/promisify@1.1.3(transitive)
+ Added@npmcli/ci-detect@1.4.0(transitive)
+ Added@npmcli/fs@1.1.1(transitive)
+ Added@npmcli/move-file@1.1.2(transitive)
+ Added@tootallnate/once@1.1.2(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedagentkeepalive@4.5.0(transitive)
+ Addedaggregate-error@3.1.0(transitive)
+ Addedcacache@15.3.0(transitive)
+ Addedchownr@2.0.0(transitive)
+ Addedclean-stack@2.2.0(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addederr-code@2.0.3(transitive)
+ Addedfs-minipass@2.1.0(transitive)
+ Addedhosted-git-info@4.1.0(transitive)
+ Addedhttp-cache-semantics@4.1.1(transitive)
+ Addedhttp-proxy-agent@4.0.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedindent-string@4.0.0(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedis-lambda@1.0.1(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedlru-cache@6.0.0(transitive)
+ Addedmake-fetch-happen@8.0.14(transitive)
+ Addedminipass@3.3.65.0.0(transitive)
+ Addedminipass-collect@1.0.2(transitive)
+ Addedminipass-fetch@1.4.1(transitive)
+ Addedminipass-flush@1.0.5(transitive)
+ Addedminipass-json-stream@1.0.2(transitive)
+ Addedminipass-pipeline@1.2.4(transitive)
+ Addedminipass-sized@1.0.3(transitive)
+ Addedminizlib@2.1.2(transitive)
+ Addedmkdirp@1.0.4(transitive)
+ Addedms@2.1.3(transitive)
+ Addednpm-package-arg@8.1.5(transitive)
+ Addednpm-registry-fetch@8.1.5(transitive)
+ Addedp-map@4.0.0(transitive)
+ Addedpromise-retry@2.0.1(transitive)
+ Addedretry@0.12.0(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsemver@7.6.3(transitive)
+ Addedsocks@2.8.3(transitive)
+ Addedsocks-proxy-agent@5.0.1(transitive)
+ Addedsprintf-js@1.1.3(transitive)
+ Addedssri@8.0.1(transitive)
+ Addedtar@6.2.1(transitive)
+ Addedyallist@4.0.0(transitive)
- Removedget-stream@^4.0.0
- RemovedJSONStream@1.3.5(transitive)
- Removedagent-base@4.2.14.3.0(transitive)
- Removedagentkeepalive@3.5.3(transitive)
- Removedaproba@1.2.0(transitive)
- Removedbluebird@3.7.2(transitive)
- Removedbuffer-from@1.1.2(transitive)
- Removedcacache@12.0.4(transitive)
- Removedchownr@1.1.4(transitive)
- Removedconcat-stream@1.6.2(transitive)
- Removedcopy-concurrently@1.0.5(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removedcyclist@1.0.2(transitive)
- Removeddebug@3.1.0(transitive)
- Removedduplexify@3.7.1(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removederr-code@1.1.2(transitive)
- Removedes6-promise@4.2.8(transitive)
- Removedes6-promisify@5.0.0(transitive)
- Removedfiggy-pudding@3.5.2(transitive)
- Removedflush-write-stream@1.1.1(transitive)
- Removedfrom2@2.3.0(transitive)
- Removedfs-write-stream-atomic@1.0.10(transitive)
- Removedget-stream@4.1.0(transitive)
- Removedgraceful-fs@4.2.11(transitive)
- Removedhosted-git-info@2.8.9(transitive)
- Removedhttp-cache-semantics@3.8.1(transitive)
- Removedhttp-proxy-agent@2.1.0(transitive)
- Removedhttps-proxy-agent@2.2.4(transitive)
- Removediferr@0.1.5(transitive)
- Removedip@1.1.5(transitive)
- Removedisarray@1.0.0(transitive)
- Removedjson-parse-better-errors@1.0.2(transitive)
- Removedlru-cache@5.1.1(transitive)
- Removedmake-fetch-happen@5.0.2(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmississippi@3.0.0(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedmove-concurrently@1.0.1(transitive)
- Removedms@2.0.0(transitive)
- Removednode-fetch-npm@2.0.4(transitive)
- Removednpm-package-arg@6.1.1(transitive)
- Removednpm-registry-fetch@4.0.7(transitive)
- Removedos-homedir@1.0.2(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedosenv@0.1.5(transitive)
- Removedparallel-transform@1.2.0(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedpromise-retry@1.1.1(transitive)
- Removedpump@2.0.13.0.2(transitive)
- Removedpumpify@1.5.1(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedretry@0.10.1(transitive)
- Removedrimraf@2.7.1(transitive)
- Removedrun-queue@1.0.3(transitive)
- Removedsafe-buffer@5.1.25.2.1(transitive)
- Removedsemver@5.7.2(transitive)
- Removedsocks@2.3.3(transitive)
- Removedsocks-proxy-agent@4.0.2(transitive)
- Removedssri@6.0.2(transitive)
- Removedstream-each@1.2.3(transitive)
- Removedstream-shift@1.0.3(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedthrough@2.3.8(transitive)
- Removedthrough2@2.0.5(transitive)
- Removedtypedarray@0.0.6(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedxtend@4.0.2(transitive)
- Removedy18n@4.0.3(transitive)
- Removedyallist@3.1.1(transitive)
Updatednpm-package-arg@^8.0.0
Updatednpm-registry-fetch@^8.0.0