Skip to content
This repository was archived by the owner on Jul 28, 2021. It is now read-only.

Commit be8735c

Browse files
Noelle Leighzkat
authored andcommitted
feat(commands): add 'deprecate' command (#23)
1 parent 6c4f80d commit be8735c

File tree

6 files changed

+465
-214
lines changed

6 files changed

+465
-214
lines changed

bin/tink.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const CMDS = new Map([
77
['shell', require('../lib/commands/shell.js')],
88
['org', require('../lib/commands/org.jsx')],
99
['prepare', require('../lib/commands/prepare.js')],
10-
['ping', require('../lib/commands/ping.js')]
10+
['ping', require('../lib/commands/ping.js')],
11+
['deprecate', require('../lib/commands/deprecate.js')]
1112
])
1213

1314
if (require.main === module) {

lib/commands/deprecate.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use strict'
2+
3+
const Deprecate = module.exports = {
4+
command: 'deprecate <pkg>[@<version>] <message>',
5+
describe: 'Deprecate a version of a package',
6+
builder (y) {
7+
return y.help().alias('help', 'h')
8+
.options(Deprecate.options)
9+
},
10+
options: Object.assign(require('../common-opts.js', {})),
11+
handler: async argv => deprecate(argv)
12+
}
13+
14+
async function deprecate (argv) {
15+
const figgyPudding = require('figgy-pudding')
16+
const BB = require('bluebird')
17+
const libnpm = require('libnpm')
18+
const npmConfig = require('../config.js')
19+
const semver = require('semver')
20+
const otplease = require('../utils/otplease.js')
21+
22+
const DeprecateConfig = figgyPudding({
23+
json: {},
24+
loglevel: {},
25+
parseable: {},
26+
silent: {}
27+
})
28+
29+
const opts = DeprecateConfig(npmConfig().concat(argv).concat({
30+
log: require('npmlog')
31+
}))
32+
33+
return BB.try(() => {
34+
// fetch the data and make sure it exists.
35+
const p = libnpm.parseArg(argv['pkg@version'])
36+
37+
// npa makes the default spec "latest", but for deprecation
38+
// "*" is the appropriate default.
39+
const spec = p.rawSpec === '' ? '*' : p.fetchSpec
40+
41+
if (semver.validRange(spec, true) === null) {
42+
throw new Error('invalid version range: ' + spec)
43+
}
44+
45+
const uri = '/' + p.escapedName
46+
return libnpm.fetch.json(uri, opts.concat({
47+
spec: p,
48+
query: { write: true }
49+
})).then(packument => {
50+
// filter all the versions that match
51+
Object.keys(packument.versions)
52+
.filter(v => semver.satisfies(v, spec))
53+
.forEach(v => { packument.versions[v].deprecated = argv.message })
54+
return otplease(opts, opts => libnpm.fetch(uri, opts.concat({
55+
spec: p,
56+
method: 'PUT',
57+
body: packument,
58+
ignoreBody: true
59+
})))
60+
})
61+
})
62+
}

lib/utils/otplease.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict'
2+
3+
const BB = require('bluebird')
4+
5+
const optCheck = require('figgy-pudding')({
6+
prompt: { default: 'This operation requires a one-time password.\nEnter OTP:' },
7+
otp: {}
8+
})
9+
10+
module.exports = otplease
11+
function otplease (opts, fn) {
12+
opts = opts.concat ? opts : optCheck(opts)
13+
return BB.try(() => {
14+
return fn(opts)
15+
}).catch(err => {
16+
if (err.code !== 'EOTP' && !(err.code === 'E401' && /one-time pass/.test(err.body))) {
17+
throw err
18+
} else if (!process.stdin.isTTY || !process.stdout.isTTY) {
19+
throw err
20+
} else {
21+
return readOTP(
22+
optCheck(opts).prompt
23+
).then(otp => fn(opts.concat({ otp })))
24+
}
25+
})
26+
}
27+
28+
function readOTP (msg, otp, isRetry) {
29+
const read = require('read')
30+
if (!msg) {
31+
msg = [
32+
'This command requires a one-time password (OTP) from your authenticator app.',
33+
'Enter one below. You can also pass one on the command line by appending --otp=123456.',
34+
'For more information, see:',
35+
'https://docs.npmjs.com/getting-started/using-two-factor-authentication',
36+
'Enter OTP: '
37+
].join('\n')
38+
}
39+
if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) return otp.replace(/\s+/g, '')
40+
41+
return read({ prompt: msg, default: otp || '' })
42+
.then((otp) => readOTP(msg, otp, true))
43+
}

0 commit comments

Comments
 (0)