1 | 'use strict'
|
2 |
|
3 | const BB = require('bluebird')
|
4 |
|
5 | const hookApi = require('libnpm/hook')
|
6 | const npmConfig = require('./config/figgy-config.js')
|
7 | const output = require('./utils/output.js')
|
8 | const otplease = require('./utils/otplease.js')
|
9 | const pudding = require('figgy-pudding')
|
10 | const relativeDate = require('tiny-relative-date')
|
11 | const Table = require('cli-table3')
|
12 | const validate = require('aproba')
|
13 |
|
14 | hook.usage = [
|
15 | 'npm hook add <pkg> <url> <secret> [--type=<type>]',
|
16 | 'npm hook ls [pkg]',
|
17 | 'npm hook rm <id>',
|
18 | 'npm hook update <id> <url> <secret>'
|
19 | ].join('\n')
|
20 |
|
21 | hook.completion = (opts, cb) => {
|
22 | validate('OF', [opts, cb])
|
23 | return cb(null, [])
|
24 | }
|
25 |
|
26 | const HookConfig = pudding({
|
27 | json: {},
|
28 | loglevel: {},
|
29 | parseable: {},
|
30 | silent: {},
|
31 | unicode: {}
|
32 | })
|
33 |
|
34 | function UsageError () {
|
35 | throw Object.assign(new Error(hook.usage), {code: 'EUSAGE'})
|
36 | }
|
37 |
|
38 | module.exports = (args, cb) => BB.try(() => hook(args)).then(
|
39 | val => cb(null, val),
|
40 | err => err.code === 'EUSAGE' ? cb(err.message) : cb(err)
|
41 | )
|
42 | function hook (args) {
|
43 | return otplease(npmConfig(), opts => {
|
44 | opts = HookConfig(opts)
|
45 | switch (args[0]) {
|
46 | case 'add':
|
47 | return add(args[1], args[2], args[3], opts)
|
48 | case 'ls':
|
49 | return ls(args[1], opts)
|
50 | case 'rm':
|
51 | return rm(args[1], opts)
|
52 | case 'update':
|
53 | case 'up':
|
54 | return update(args[1], args[2], args[3], opts)
|
55 | default:
|
56 | UsageError()
|
57 | }
|
58 | })
|
59 | }
|
60 |
|
61 | function add (pkg, uri, secret, opts) {
|
62 | return hookApi.add(pkg, uri, secret, opts).then(hook => {
|
63 | if (opts.json) {
|
64 | output(JSON.stringify(hook, null, 2))
|
65 | } else if (opts.parseable) {
|
66 | output(Object.keys(hook).join('\t'))
|
67 | output(Object.keys(hook).map(k => hook[k]).join('\t'))
|
68 | } else if (!opts.silent && opts.loglevel !== 'silent') {
|
69 | output(`+ ${hookName(hook)} ${
|
70 | opts.unicode ? ' ➜ ' : ' -> '
|
71 | } ${hook.endpoint}`)
|
72 | }
|
73 | })
|
74 | }
|
75 |
|
76 | function ls (pkg, opts) {
|
77 | return hookApi.ls(opts.concat({package: pkg})).then(hooks => {
|
78 | if (opts.json) {
|
79 | output(JSON.stringify(hooks, null, 2))
|
80 | } else if (opts.parseable) {
|
81 | output(Object.keys(hooks[0]).join('\t'))
|
82 | hooks.forEach(hook => {
|
83 | output(Object.keys(hook).map(k => hook[k]).join('\t'))
|
84 | })
|
85 | } else if (!hooks.length) {
|
86 | output("You don't have any hooks configured yet.")
|
87 | } else if (!opts.silent && opts.loglevel !== 'silent') {
|
88 | if (hooks.length === 1) {
|
89 | output('You have one hook configured.')
|
90 | } else {
|
91 | output(`You have ${hooks.length} hooks configured.`)
|
92 | }
|
93 | const table = new Table({head: ['id', 'target', 'endpoint']})
|
94 | hooks.forEach((hook) => {
|
95 | table.push([
|
96 | {rowSpan: 2, content: hook.id},
|
97 | hookName(hook),
|
98 | hook.endpoint
|
99 | ])
|
100 | if (hook.last_delivery) {
|
101 | table.push([
|
102 | {
|
103 | colSpan: 1,
|
104 | content: `triggered ${relativeDate(hook.last_delivery)}`
|
105 | },
|
106 | hook.response_code
|
107 | ])
|
108 | } else {
|
109 | table.push([{colSpan: 2, content: 'never triggered'}])
|
110 | }
|
111 | })
|
112 | output(table.toString())
|
113 | }
|
114 | })
|
115 | }
|
116 |
|
117 | function rm (id, opts) {
|
118 | return hookApi.rm(id, opts).then(hook => {
|
119 | if (opts.json) {
|
120 | output(JSON.stringify(hook, null, 2))
|
121 | } else if (opts.parseable) {
|
122 | output(Object.keys(hook).join('\t'))
|
123 | output(Object.keys(hook).map(k => hook[k]).join('\t'))
|
124 | } else if (!opts.silent && opts.loglevel !== 'silent') {
|
125 | output(`- ${hookName(hook)} ${
|
126 | opts.unicode ? ' ✘ ' : ' X '
|
127 | } ${hook.endpoint}`)
|
128 | }
|
129 | })
|
130 | }
|
131 |
|
132 | function update (id, uri, secret, opts) {
|
133 | return hookApi.update(id, uri, secret, opts).then(hook => {
|
134 | if (opts.json) {
|
135 | output(JSON.stringify(hook, null, 2))
|
136 | } else if (opts.parseable) {
|
137 | output(Object.keys(hook).join('\t'))
|
138 | output(Object.keys(hook).map(k => hook[k]).join('\t'))
|
139 | } else if (!opts.silent && opts.loglevel !== 'silent') {
|
140 | output(`+ ${hookName(hook)} ${
|
141 | opts.unicode ? ' ➜ ' : ' -> '
|
142 | } ${hook.endpoint}`)
|
143 | }
|
144 | })
|
145 | }
|
146 |
|
147 | function hookName (hook) {
|
148 | let target = hook.name
|
149 | if (hook.type === 'scope') { target = '@' + target }
|
150 | if (hook.type === 'owner') { target = '~' + target }
|
151 | return target
|
152 | }
|