1 | # heroku-cli-util [![Circle CI](https://circleci.com/gh/heroku/heroku-cli-util/tree/master.svg?style=svg)](https://circleci.com/gh/heroku/heroku-cli-util/tree/master)
|
2 |
|
3 | [![Code Climate](https://codeclimate.com/github/heroku/heroku-cli-util/badges/gpa.svg)](https://codeclimate.com/github/heroku/heroku-cli-util)
|
4 | [![Test Coverage](https://codeclimate.com/github/heroku/heroku-cli-util/badges/coverage.svg)](https://codeclimate.com/github/heroku/heroku-cli-util/coverage)
|
5 | [![npm version](https://badge.fury.io/js/heroku-cli-util.svg)](http://badge.fury.io/js/heroku-cli-util)
|
6 | [![License](https://img.shields.io/github/license/heroku/heroku-cli-util.svg)](https://github.com/heroku/heroku-cli-util/blob/master/LICENSE)
|
7 |
|
8 | Set of helpful CLI utilities
|
9 |
|
10 | ## Installation
|
11 |
|
12 | ```sh
|
13 | npm install heroku-cli-util --save
|
14 | ```
|
15 |
|
16 | ## Action
|
17 |
|
18 | ```js
|
19 | let cli = require('heroku-cli-util');
|
20 | yield cli.action('restarting dynos', co(function* () {
|
21 | let app = yield heroku.get(`/apps/${context.app}`);
|
22 | yield heroku.request({method: 'DELETE', path: `/apps/${app.name}/dynos`});
|
23 | }));
|
24 |
|
25 | // restarting dynos... done
|
26 | ```
|
27 |
|
28 | ## Prompt
|
29 |
|
30 | ```js
|
31 | let cli = require('heroku-cli-util');
|
32 | let email = yield cli.prompt('email', {});
|
33 | console.log(`your email is: ${email}`);
|
34 | ```
|
35 |
|
36 | **cli.prompt options**
|
37 |
|
38 | ```js
|
39 | cli.prompt('email', {
|
40 | mask: true, // mask input field after submitting
|
41 | hide: true // mask characters while entering
|
42 | });
|
43 | ```
|
44 |
|
45 | ## Confirm App
|
46 |
|
47 | Supports the same async styles as `prompt()`. Errors if not confirmed.
|
48 |
|
49 | Basic
|
50 |
|
51 | ```js
|
52 | let cli = require('heroku-cli-util');
|
53 | yield cli.confirmApp('appname', context.flags.confirm);
|
54 |
|
55 | // ! WARNING: Destructive Action
|
56 | // ! This command will affect the app appname
|
57 | // ! To proceed, type appname or re-run this command with --confirm appname
|
58 |
|
59 | > appname
|
60 | ```
|
61 |
|
62 | Custom message
|
63 |
|
64 | ```js
|
65 | let cli = require('heroku-cli-util');
|
66 | yield cli.confirmApp('appname', context.flags.confirm, 'foo');
|
67 |
|
68 | // ! foo
|
69 | // ! To proceed, type appname or re-run this command with --confirm appname
|
70 |
|
71 | > appname
|
72 | ```
|
73 |
|
74 | Note that you will still need to define a `confirm` flag for your command.
|
75 |
|
76 | ## Errors
|
77 |
|
78 | ```js
|
79 | let cli = require('heroku-cli-util');
|
80 | cli.error("App not found");
|
81 | // ! App not found
|
82 | ```
|
83 |
|
84 | ## Warnings
|
85 |
|
86 | ```js
|
87 | let cli = require('heroku-cli-util');
|
88 | cli.warn("App not found");
|
89 | // ! App not found
|
90 | ```
|
91 |
|
92 | ## Dates
|
93 |
|
94 | ```js
|
95 | let cli = require('heroku-cli-util');
|
96 | let d = new Date();
|
97 | console.log(cli.formatDate(d));
|
98 | // 2001-01-01T08:00:00.000Z
|
99 | ```
|
100 |
|
101 | ## Hush
|
102 |
|
103 | Use hush for verbose logging when `HEROKU_DEBUG=1`.
|
104 |
|
105 | ```js
|
106 | let cli = require('heroku-cli-util');
|
107 | cli.hush('foo');
|
108 | // only prints if HEROKU_DEBUG is set
|
109 | ```
|
110 |
|
111 | ## Debug
|
112 |
|
113 | Pretty print an object.
|
114 |
|
115 | ```js
|
116 | let cli = require('heroku-cli-util');
|
117 | cli.debug({foo: [1,2,3]});
|
118 | // { foo: [ 1, 2, 3 ] }
|
119 | ```
|
120 |
|
121 | ## Stylized output
|
122 |
|
123 | Pretty print a header, hash, and JSON
|
124 | ```js
|
125 | let cli = require('heroku-cli-util');
|
126 | cli.styledHeader("MyApp");
|
127 | cli.styledHash({name: "myapp", collaborators: ["user1@example.com", "user2@example.com"]});
|
128 | cli.styledJSON({name: "myapp"});
|
129 | ```
|
130 |
|
131 | Produces
|
132 |
|
133 | ```
|
134 | === MyApp
|
135 | Collaborators: user1@example.com
|
136 | user1@example.com
|
137 | Name: myapp
|
138 |
|
139 | {
|
140 | "name": "myapp"
|
141 | }
|
142 | ```
|
143 |
|
144 | ## Table
|
145 |
|
146 | ```js
|
147 | cli.table([
|
148 | {app: 'first-app', language: 'ruby', dyno_count: 3},
|
149 | {app: 'second-app', language: 'node', dyno_count: 2},
|
150 | ], {
|
151 | columns: [
|
152 | {key: 'app'},
|
153 | {key: 'dyno_count', label: 'Dyno Count'},
|
154 | {key: 'language', format: language => cli.color.red(language)},
|
155 | ]
|
156 | });
|
157 | ```
|
158 |
|
159 | Produces:
|
160 |
|
161 | ```
|
162 | app Dyno Count language
|
163 | ────────── ────────── ────────
|
164 | first-app 3 ruby
|
165 | second-app 2 node
|
166 | ```
|
167 |
|
168 | ## Linewrap
|
169 |
|
170 | Used to indent output with wrapping around words:
|
171 |
|
172 | ```js
|
173 | cli.log(cli.linewrap(2, 10, 'this is text is longer than 10 characters'));
|
174 | // Outputs:
|
175 | //
|
176 | // this
|
177 | // text is
|
178 | // longer
|
179 | // than 10
|
180 | // characters`);
|
181 | ```
|
182 |
|
183 | Useful with `process.stdout.columns || 80`.
|
184 |
|
185 | ## Open Web Browser
|
186 |
|
187 | ```js
|
188 | yield cli.open('https://github.com');
|
189 | ```
|
190 |
|
191 | ## HTTP calls
|
192 |
|
193 | `heroku-cli-util` includes an instance of [got](https://www.npmjs.com/package/got) that will correctly use HTTP proxies.
|
194 |
|
195 | ```js
|
196 | let cli = require('heroku-cli-util');
|
197 | let rsp = yield cli.got('https://google.com');
|
198 | ```
|
199 |
|
200 | ## Mocking
|
201 |
|
202 | Mock stdout and stderr by using `cli.log()` and `cli.error()`.
|
203 |
|
204 | ```js
|
205 | let cli = require('heroku-cli-util');
|
206 | cli.log('message 1'); // prints 'message 1'
|
207 | cli.mockConsole();
|
208 | cli.log('message 2'); // prints nothing
|
209 | cli.stdout.should.eq('message 2\n');
|
210 | ```
|
211 |
|
212 | ## Command
|
213 |
|
214 | Used for initializing a plugin command.
|
215 | give you an auth'ed instance of `heroku-client` and cleanly handle API exceptions.
|
216 |
|
217 | It expects you to return a promise chain. This is usually done with [co](https://github.com/tj/co).
|
218 |
|
219 | ```js
|
220 | let cli = require('heroku-cli-util');
|
221 | let co = require('co');
|
222 | module.exports.commands = [
|
223 | {
|
224 | topic: 'apps',
|
225 | command: 'info',
|
226 | needsAuth: true,
|
227 | needsApp: true,
|
228 | run: cli.command(function (context, heroku) {
|
229 | return co(function* () {
|
230 | let app = yield heroku.get(`/apps/${context.app}`);
|
231 | console.dir(app);
|
232 | });
|
233 | })
|
234 | }
|
235 | ];
|
236 | ```
|
237 |
|
238 | With options:
|
239 |
|
240 | ```js
|
241 | let cli = require('heroku-cli-util');
|
242 | let co = require('co');
|
243 | module.exports.commands = [
|
244 | {
|
245 | topic: 'apps',
|
246 | command: 'info',
|
247 | needsAuth: true,
|
248 | needsApp: true,
|
249 | run: cli.command(
|
250 | {preauth: true},
|
251 | function (context, heroku) {
|
252 | return co(function* () {
|
253 | let app = yield heroku.get(`/apps/${context.app}`);
|
254 | console.dir(app);
|
255 | });
|
256 | }
|
257 | )
|
258 | }
|
259 | ];
|
260 | ```
|
261 |
|
262 | If the command has a `two_factor` API error, it will ask the user for a 2fa code and retry.
|
263 | If you set `preauth: true` it will preauth against the current app instead of just setting the header on an app. (This is necessary if you need to do more than 1 API call that will require 2fa)
|
264 |
|
265 | ## Tests
|
266 |
|
267 | ```sh
|
268 | npm install
|
269 | npm test
|
270 | ```
|
271 |
|
272 | ## License
|
273 |
|
274 | ISC
|