1const hookApi = require('libnpmhook') 2const otplease = require('../utils/otplease.js') 3const relativeDate = require('tiny-relative-date') 4const Table = require('cli-table3') 5 6const BaseCommand = require('../base-command.js') 7class Hook extends BaseCommand { 8 static description = 'Manage registry hooks' 9 static name = 'hook' 10 static params = [ 11 'registry', 12 'otp', 13 ] 14 15 static usage = [ 16 'add <pkg> <url> <secret> [--type=<type>]', 17 'ls [pkg]', 18 'rm <id>', 19 'update <id> <url> <secret>', 20 ] 21 22 async exec (args) { 23 return otplease(this.npm, { ...this.npm.flatOptions }, (opts) => { 24 switch (args[0]) { 25 case 'add': 26 return this.add(args[1], args[2], args[3], opts) 27 case 'ls': 28 return this.ls(args[1], opts) 29 case 'rm': 30 return this.rm(args[1], opts) 31 case 'update': 32 case 'up': 33 return this.update(args[1], args[2], args[3], opts) 34 default: 35 throw this.usageError() 36 } 37 }) 38 } 39 40 async add (pkg, uri, secret, opts) { 41 const hook = await hookApi.add(pkg, uri, secret, opts) 42 if (opts.json) { 43 this.npm.output(JSON.stringify(hook, null, 2)) 44 } else if (opts.parseable) { 45 this.npm.output(Object.keys(hook).join('\t')) 46 this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) 47 } else if (!this.npm.silent) { 48 this.npm.output(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) 49 } 50 } 51 52 async ls (pkg, opts) { 53 const hooks = await hookApi.ls({ ...opts, package: pkg }) 54 if (opts.json) { 55 this.npm.output(JSON.stringify(hooks, null, 2)) 56 } else if (opts.parseable) { 57 this.npm.output(Object.keys(hooks[0]).join('\t')) 58 hooks.forEach(hook => { 59 this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) 60 }) 61 } else if (!hooks.length) { 62 this.npm.output("You don't have any hooks configured yet.") 63 } else if (!this.npm.silent) { 64 if (hooks.length === 1) { 65 this.npm.output('You have one hook configured.') 66 } else { 67 this.npm.output(`You have ${hooks.length} hooks configured.`) 68 } 69 70 const table = new Table({ head: ['id', 'target', 'endpoint'] }) 71 hooks.forEach((hook) => { 72 table.push([ 73 { rowSpan: 2, content: hook.id }, 74 this.hookName(hook), 75 hook.endpoint, 76 ]) 77 if (hook.last_delivery) { 78 table.push([ 79 { 80 colSpan: 1, 81 content: `triggered ${relativeDate(hook.last_delivery)}`, 82 }, 83 hook.response_code, 84 ]) 85 } else { 86 table.push([{ colSpan: 2, content: 'never triggered' }]) 87 } 88 }) 89 this.npm.output(table.toString()) 90 } 91 } 92 93 async rm (id, opts) { 94 const hook = await hookApi.rm(id, opts) 95 if (opts.json) { 96 this.npm.output(JSON.stringify(hook, null, 2)) 97 } else if (opts.parseable) { 98 this.npm.output(Object.keys(hook).join('\t')) 99 this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) 100 } else if (!this.npm.silent) { 101 this.npm.output(`- ${this.hookName(hook)} ${opts.unicode ? ' ✘ ' : ' X '} ${hook.endpoint}`) 102 } 103 } 104 105 async update (id, uri, secret, opts) { 106 const hook = await hookApi.update(id, uri, secret, opts) 107 if (opts.json) { 108 this.npm.output(JSON.stringify(hook, null, 2)) 109 } else if (opts.parseable) { 110 this.npm.output(Object.keys(hook).join('\t')) 111 this.npm.output(Object.keys(hook).map(k => hook[k]).join('\t')) 112 } else if (!this.npm.silent) { 113 this.npm.output(`+ ${this.hookName(hook)} ${opts.unicode ? ' ➜ ' : ' -> '} ${hook.endpoint}`) 114 } 115 } 116 117 hookName (hook) { 118 let target = hook.name 119 if (hook.type === 'owner') { 120 target = '~' + target 121 } 122 return target 123 } 124} 125module.exports = Hook 126