codekingpro/portable-devtools
114k
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 cannot 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 