1'use strict' 2 3const npa = require('npm-package-arg') 4const npmFetch = require('npm-registry-fetch') 5 6const npar = (spec) => { 7 spec = npa(spec) 8 if (!spec.registry) { 9 throw new Error('must use package name only') 10 } 11 return spec 12} 13 14const parseTeam = (scopeTeam) => { 15 let slice = 0 16 if (scopeTeam.startsWith('@')) { 17 slice = 1 18 } 19 const [scope, team] = scopeTeam.slice(slice).split(':').map(encodeURIComponent) 20 return { scope, team } 21} 22 23const getPackages = async (scopeTeam, opts) => { 24 const { scope, team } = parseTeam(scopeTeam) 25 26 let uri 27 if (team) { 28 uri = `/-/team/${scope}/${team}/package` 29 } else { 30 uri = `/-/org/${scope}/package` 31 } 32 try { 33 return await npmFetch.json(uri, opts) 34 } catch (err) { 35 if (err.code === 'E404') { 36 uri = `/-/user/${scope}/package` 37 return npmFetch.json(uri, opts) 38 } 39 throw err 40 } 41} 42 43const getCollaborators = async (pkg, opts) => { 44 const spec = npar(pkg) 45 const uri = `/-/package/${spec.escapedName}/collaborators` 46 return npmFetch.json(uri, opts) 47} 48 49const getVisibility = async (pkg, opts) => { 50 const spec = npar(pkg) 51 const uri = `/-/package/${spec.escapedName}/visibility` 52 return npmFetch.json(uri, opts) 53} 54 55const setAccess = async (pkg, access, opts) => { 56 const spec = npar(pkg) 57 const uri = `/-/package/${spec.escapedName}/access` 58 await npmFetch(uri, { 59 ...opts, 60 method: 'POST', 61 body: { access }, 62 spec, 63 ignoreBody: true, 64 }) 65 return true 66} 67 68const setMfa = async (pkg, level, opts) => { 69 const spec = npar(pkg) 70 const body = {} 71 switch (level) { 72 case 'none': 73 body.publish_requires_tfa = false 74 break 75 case 'publish': 76 // tfa is required, automation tokens can not override tfa 77 body.publish_requires_tfa = true 78 body.automation_token_overrides_tfa = false 79 break 80 case 'automation': 81 // tfa is required, automation tokens can override tfa 82 body.publish_requires_tfa = true 83 body.automation_token_overrides_tfa = true 84 break 85 default: 86 throw new Error(`Invalid mfa setting ${level}`) 87 } 88 const uri = `/-/package/${spec.escapedName}/access` 89 await npmFetch(uri, { 90 ...opts, 91 method: 'POST', 92 body, 93 spec, 94 ignoreBody: true, 95 }) 96 return true 97} 98 99const setPermissions = async (scopeTeam, pkg, permissions, opts) => { 100 const spec = npar(pkg) 101 const { scope, team } = parseTeam(scopeTeam) 102 if (!scope || !team) { 103 throw new Error('team must be in format `scope:team`') 104 } 105 const uri = `/-/team/${scope}/${team}/package` 106 await npmFetch(uri, { 107 ...opts, 108 method: 'PUT', 109 body: { package: spec.name, permissions }, 110 scope, 111 spec, 112 ignoreBody: true, 113 }) 114 return true 115} 116 117const removePermissions = async (scopeTeam, pkg, opts) => { 118 const spec = npar(pkg) 119 const { scope, team } = parseTeam(scopeTeam) 120 const uri = `/-/team/${scope}/${team}/package` 121 await npmFetch(uri, { 122 ...opts, 123 method: 'DELETE', 124 body: { package: spec.name }, 125 scope, 126 spec, 127 ignoreBody: true, 128 }) 129 return true 130} 131 132module.exports = { 133 getCollaborators, 134 getPackages, 135 getVisibility, 136 removePermissions, 137 setAccess, 138 setMfa, 139 setPermissions, 140} 141