xref: /third_party/node/deps/npm/lib/commands/hook.js (revision 1cb0ef41)
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