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

Commit

Permalink
feat(commands): add 'deprecate' command (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
Noelle Leigh authored and zkat committed Nov 12, 2018
1 parent 6c4f80d commit be8735c
Show file tree
Hide file tree
Showing 6 changed files with 465 additions and 214 deletions.
3 changes: 2 additions & 1 deletion bin/tink.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const CMDS = new Map([
['shell', require('../lib/commands/shell.js')],
['org', require('../lib/commands/org.jsx')],
['prepare', require('../lib/commands/prepare.js')],
['ping', require('../lib/commands/ping.js')]
['ping', require('../lib/commands/ping.js')],
['deprecate', require('../lib/commands/deprecate.js')]
])

if (require.main === module) {
Expand Down
62 changes: 62 additions & 0 deletions lib/commands/deprecate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict'

const Deprecate = module.exports = {
command: 'deprecate <pkg>[@<version>] <message>',
describe: 'Deprecate a version of a package',
builder (y) {
return y.help().alias('help', 'h')
.options(Deprecate.options)
},
options: Object.assign(require('../common-opts.js', {})),
handler: async argv => deprecate(argv)
}

async function deprecate (argv) {
const figgyPudding = require('figgy-pudding')
const BB = require('bluebird')
const libnpm = require('libnpm')
const npmConfig = require('../config.js')
const semver = require('semver')
const otplease = require('../utils/otplease.js')

const DeprecateConfig = figgyPudding({
json: {},
loglevel: {},
parseable: {},
silent: {}
})

const opts = DeprecateConfig(npmConfig().concat(argv).concat({
log: require('npmlog')
}))

return BB.try(() => {
// fetch the data and make sure it exists.
const p = libnpm.parseArg(argv['pkg@version'])

// npa makes the default spec "latest", but for deprecation
// "*" is the appropriate default.
const spec = p.rawSpec === '' ? '*' : p.fetchSpec

if (semver.validRange(spec, true) === null) {
throw new Error('invalid version range: ' + spec)
}

const uri = '/' + p.escapedName
return libnpm.fetch.json(uri, opts.concat({
spec: p,
query: { write: true }
})).then(packument => {
// filter all the versions that match
Object.keys(packument.versions)
.filter(v => semver.satisfies(v, spec))
.forEach(v => { packument.versions[v].deprecated = argv.message })
return otplease(opts, opts => libnpm.fetch(uri, opts.concat({
spec: p,
method: 'PUT',
body: packument,
ignoreBody: true
})))
})
})
}
43 changes: 43 additions & 0 deletions lib/utils/otplease.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict'

const BB = require('bluebird')

const optCheck = require('figgy-pudding')({
prompt: { default: 'This operation requires a one-time password.\nEnter OTP:' },
otp: {}
})

module.exports = otplease
function otplease (opts, fn) {
opts = opts.concat ? opts : optCheck(opts)
return BB.try(() => {
return fn(opts)
}).catch(err => {
if (err.code !== 'EOTP' && !(err.code === 'E401' && /one-time pass/.test(err.body))) {
throw err
} else if (!process.stdin.isTTY || !process.stdout.isTTY) {
throw err
} else {
return readOTP(
optCheck(opts).prompt
).then(otp => fn(opts.concat({ otp })))
}
})
}

function readOTP (msg, otp, isRetry) {
const read = require('read')
if (!msg) {
msg = [
'This command requires a one-time password (OTP) from your authenticator app.',
'Enter one below. You can also pass one on the command line by appending --otp=123456.',
'For more information, see:',
'https://docs.npmjs.com/getting-started/using-two-factor-authentication',
'Enter OTP: '
].join('\n')
}
if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) return otp.replace(/\s+/g, '')

return read({ prompt: msg, default: otp || '' })
.then((otp) => readOTP(msg, otp, true))
}
Loading

0 comments on commit be8735c

Please sign in to comment.