@heroku/heroku-cli-util 8.0.14 → 9.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +15 -3
  2. package/README.md +44 -241
  3. package/dist/test-helpers/expect-output.d.ts +2 -0
  4. package/dist/test-helpers/expect-output.js +16 -0
  5. package/dist/test-helpers/init.d.ts +1 -0
  6. package/dist/test-helpers/init.js +18 -0
  7. package/dist/test-helpers/stub-output.d.ts +2 -0
  8. package/dist/test-helpers/stub-output.js +33 -0
  9. package/dist/types/errors/ambiguous.d.ts +15 -0
  10. package/dist/types/errors/ambiguous.js +14 -0
  11. package/dist/types/errors/not-found.d.ts +5 -0
  12. package/dist/types/errors/not-found.js +12 -0
  13. package/dist/types/pg/data-api.d.ts +17 -0
  14. package/dist/types/pg/data-api.js +2 -0
  15. package/dist/types/pg/tunnel.d.ts +22 -0
  16. package/dist/types/pg/tunnel.js +2 -0
  17. package/dist/utils/addons/resolve.d.ts +9 -0
  18. package/dist/utils/addons/resolve.js +39 -0
  19. package/dist/utils/pg/bastion.d.ts +30 -0
  20. package/dist/utils/pg/bastion.js +122 -0
  21. package/dist/utils/pg/config-vars.d.ts +8 -0
  22. package/dist/utils/pg/config-vars.js +34 -0
  23. package/dist/utils/pg/databases.d.ts +12 -0
  24. package/dist/utils/pg/databases.js +137 -0
  25. package/dist/utils/pg/host.d.ts +1 -0
  26. package/dist/utils/pg/host.js +7 -0
  27. package/dist/utils/pg/psql.d.ts +28 -0
  28. package/dist/utils/pg/psql.js +188 -0
  29. package/dist/ux/confirm.d.ts +1 -0
  30. package/dist/ux/confirm.js +7 -0
  31. package/dist/ux/prompt.d.ts +2 -0
  32. package/dist/ux/prompt.js +7 -0
  33. package/dist/ux/styled-header.d.ts +1 -0
  34. package/dist/ux/styled-header.js +7 -0
  35. package/dist/ux/styled-json.d.ts +1 -0
  36. package/dist/ux/styled-json.js +7 -0
  37. package/dist/ux/styled-object.d.ts +1 -0
  38. package/dist/ux/styled-object.js +7 -0
  39. package/dist/ux/table.d.ts +2 -0
  40. package/dist/ux/table.js +7 -0
  41. package/dist/ux/wait.d.ts +1 -0
  42. package/dist/ux/wait.js +7 -0
  43. package/package.json +54 -55
  44. package/index.js +0 -40
  45. package/lib/action.js +0 -54
  46. package/lib/auth.js +0 -207
  47. package/lib/command.js +0 -171
  48. package/lib/console.js +0 -105
  49. package/lib/date.js +0 -18
  50. package/lib/errors.js +0 -122
  51. package/lib/exit.js +0 -42
  52. package/lib/got.js +0 -153
  53. package/lib/linewrap.js +0 -783
  54. package/lib/mutex.js +0 -41
  55. package/lib/open.js +0 -22
  56. package/lib/preauth.js +0 -26
  57. package/lib/process.js +0 -14
  58. package/lib/prompt.js +0 -150
  59. package/lib/spinner.js +0 -147
  60. package/lib/spinners.json +0 -739
  61. package/lib/styled.js +0 -131
  62. package/lib/table.js +0 -132
  63. package/lib/util.js +0 -38
  64. package/lib/vars.js +0 -29
  65. package/lib/yubikey.js +0 -14
package/package.json CHANGED
@@ -1,70 +1,69 @@
1
1
  {
2
+ "type": "commonjs",
2
3
  "name": "@heroku/heroku-cli-util",
4
+ "version": "9.0.0-beta.0",
3
5
  "description": "Set of helpful CLI utilities",
4
- "version": "8.0.14",
5
6
  "author": "Heroku",
6
- "bugs": {
7
- "url": "https://github.com/heroku/heroku-cli-util/issues"
7
+ "license": "ISC",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "devDependencies": {
14
+ "@heroku-cli/schema": "^2.0.0",
15
+ "@types/chai": "^4.3.13",
16
+ "@types/debug": "^4.1.12",
17
+ "@types/mocha": "^10.0.10",
18
+ "@types/node": "^22.15.3",
19
+ "@types/sinon": "^17.0.4",
20
+ "@types/tunnel-ssh": "4.1.1",
21
+ "chai": "^4.4.1",
22
+ "eslint": "^8.57.0",
23
+ "eslint-config-oclif": "^5.0.0",
24
+ "eslint-config-oclif-typescript": "^3.1.14",
25
+ "eslint-plugin-import": "^2.31.0",
26
+ "eslint-plugin-mocha": "^10.4.3",
27
+ "mocha": "^10.8.2",
28
+ "nyc": "^17.1.0",
29
+ "sinon": "^18.0.1",
30
+ "strip-ansi": "^6",
31
+ "ts-node": "^10.9.2",
32
+ "tsconfig-paths": "^4.2.0",
33
+ "tsheredoc": "^1.0.1",
34
+ "typescript": "^5.4.0"
8
35
  },
9
36
  "dependencies": {
10
- "@heroku-cli/color": "^1.1.3",
11
- "ansi-escapes": "^3.1.0",
12
- "ansi-styles": "^3.2.1",
13
- "cardinal": "^2.0.1",
14
- "chalk": "^2.4.1",
15
- "got": "^11.8.6",
16
- "heroku-client": "^3.1.0",
17
- "lodash": "^4.17.10",
18
- "netrc-parser": "^3.1.4",
19
- "opn": "^3.0.3",
20
- "strip-ansi": "^4.0.0",
21
- "supports-color": "^9.4.0",
22
- "tslib": "^1.9.0",
23
- "tunnel-agent": "^0.6.0"
24
- },
25
- "devDependencies": {
26
- "chai": "^4.1.2",
27
- "co": "^4.6.0",
28
- "hook-std": "^0.4.0",
29
- "mocha": "^10.2.0",
30
- "mocha-junit-reporter": "^2.2.1",
31
- "nock": "^11.9.1",
32
- "nyc": "^15.1.0",
33
- "proxyquire": "^1.7.11",
34
- "sinon": "^18.0.0",
35
- "standard": "^12.0.1",
36
- "tmp": "^0.0.33",
37
- "unexpected": "^13.2.1"
37
+ "@oclif/core": "^2.16.0",
38
+ "@heroku/http-call": "^5.4.0",
39
+ "@heroku-cli/color": "^2.0.4",
40
+ "@heroku-cli/command": "^11.5.0",
41
+ "debug": "^4.4.0",
42
+ "nock": "^13.2.9",
43
+ "tunnel-ssh": "4.1.6"
38
44
  },
39
45
  "engines": {
40
- "node": ">= 14"
46
+ "node": ">=20"
41
47
  },
42
- "files": [
43
- "lib",
44
- "index.js"
45
- ],
46
- "homepage": "https://github.com/heroku/heroku-cli-util",
47
- "license": "ISC",
48
- "main": "index.js",
49
48
  "mocha": {
50
49
  "require": [
51
- "./test/init"
52
- ]
50
+ "ts-node/register",
51
+ "source-map-support/register"
52
+ ],
53
+ "file": [
54
+ "src/test-helpers/stub-output.ts"
55
+ ],
56
+ "watch-extensions": "ts",
57
+ "recursive": true,
58
+ "reporter": "spec",
59
+ "timeout": 360000
53
60
  },
54
- "nyc": {
55
- "exclude": [
56
- "lib/linewrap.js"
57
- ]
58
- },
59
- "repository": "heroku/heroku-cli-util",
60
61
  "scripts": {
61
- "test": "mocha",
62
- "posttest": "standard"
63
- },
64
- "standard": {
65
- "env": "mocha",
66
- "ignore": [
67
- "lib/linewrap.js"
68
- ]
62
+ "build": "tsc",
63
+ "clean": "rm -rf dist",
64
+ "lint": "eslint . --ext .ts --config .eslintrc.js",
65
+ "prepare": "npm run clean && npm run build",
66
+ "test": "nyc mocha --forbid-only \"test/**/*.test.ts\"",
67
+ "test:local": "mocha \"test/**/*.test.ts\""
69
68
  }
70
69
  }
package/index.js DELETED
@@ -1,40 +0,0 @@
1
- 'use strict'
2
-
3
- exports.color = require('@heroku-cli/color').default
4
-
5
- var console = require('./lib/console')
6
- var errors = require('./lib/errors')
7
- var prompt = require('./lib/prompt')
8
- var styled = require('./lib/styled')
9
-
10
- exports.hush = console.hush
11
- exports.log = console.log.bind(console)
12
- exports.formatDate = require('./lib/date').formatDate
13
- exports.error = errors.error
14
- exports.action = require('./lib/action')
15
- exports.warn = exports.action.warn
16
- exports.errorHandler = errors.errorHandler
17
- exports.console = console
18
- exports.yubikey = require('./lib/yubikey')
19
- exports.prompt = prompt.prompt
20
- exports.confirmApp = prompt.confirmApp
21
- exports.preauth = require('./lib/preauth')
22
- exports.command = require('./lib/command')
23
- exports.debug = console.debug
24
- exports.mockConsole = console.mock
25
- exports.table = require('./lib/table')
26
- exports.stdout = ''
27
- exports.stderr = ''
28
- exports.styledHeader = styled.styledHeader
29
- exports.styledObject = styled.styledObject
30
- exports.styledHash = styled.styledObject
31
- exports.styledNameValues = styled.styledNameValues
32
- exports.styledJSON = styled.styledJSON
33
- exports.open = require('./lib/open')
34
- exports.got = require('./lib/got')
35
- exports.linewrap = require('./lib/linewrap')
36
- exports.Spinner = require('./lib/spinner')
37
- exports.exit = require('./lib/exit').exit
38
- exports.auth = require('./lib/auth')
39
- exports.login = exports.auth.login
40
- exports.logout = exports.auth.logout
package/lib/action.js DELETED
@@ -1,54 +0,0 @@
1
- 'use strict'
2
-
3
- let cli = require('..')
4
- let errors = require('./errors')
5
-
6
- function start (message, options) {
7
- if (!options) options = {}
8
- module.exports.task = {
9
- spinner: new cli.Spinner({ spinner: options.spinner, text: `${message}...` }),
10
- stream: options.stream
11
- }
12
- module.exports.task.spinner.start()
13
- }
14
-
15
- function action (message, options, promise) {
16
- if (options.then) [options, promise] = [{}, options]
17
- start(message, options)
18
- return promise.then(function (result) {
19
- if (options.success !== false) done(options.success || 'done', options)
20
- else done(null, options)
21
- return result
22
- }).catch(function (err) {
23
- if (err.body && err.body.id === 'two_factor') done(cli.color.yellow.bold('!'), options)
24
- else done(cli.color.red.bold('!'), options)
25
- throw err
26
- })
27
- }
28
-
29
- function warn (msg) {
30
- let task = module.exports.task
31
- if (task) task.spinner.warn(msg)
32
- else errors.warn(msg)
33
- }
34
-
35
- function status (status) {
36
- let task = module.exports.task
37
- if (task) task.spinner.status = status
38
- }
39
-
40
- function done (msg, options) {
41
- options = options || {}
42
- let task = module.exports.task
43
- if (task) {
44
- task.spinner.stop(msg)
45
- module.exports.task = null
46
- if (options.clear) task.spinner.clear()
47
- }
48
- }
49
-
50
- module.exports = action
51
- module.exports.start = start
52
- module.exports.warn = warn
53
- module.exports.status = status
54
- module.exports.done = done
package/lib/auth.js DELETED
@@ -1,207 +0,0 @@
1
- 'use strict'
2
-
3
- const cli = require('..')
4
- const vars = require('./vars')
5
-
6
- function basicAuth (username, password) {
7
- let auth = [username, password].join(':')
8
- auth = Buffer.from(auth).toString('base64')
9
- return `Basic ${auth}`
10
- }
11
-
12
- function createOAuthToken (username, password, expiresIn, secondFactor) {
13
- const os = require('os')
14
-
15
- let headers = {
16
- Authorization: basicAuth(username, password)
17
- }
18
-
19
- if (secondFactor) headers['Heroku-Two-Factor-Code'] = secondFactor
20
-
21
- return cli.heroku.post('/oauth/authorizations', {
22
- headers,
23
- body: {
24
- scope: ['global'],
25
- description: `Heroku CLI login from ${os.hostname()} at ${new Date()}`,
26
- expires_in: expiresIn || 60 * 60 * 24 * 365 // 1 year
27
- }
28
- }).then(function (auth) {
29
- return { token: auth.access_token.token, email: auth.user.email, expires_in: auth.access_token.expires_in }
30
- })
31
- }
32
-
33
- function saveToken ({ email, token }) {
34
- const netrc = require('netrc-parser').default
35
- netrc.loadSync()
36
- const hosts = [vars.apiHost, vars.httpGitHost]
37
- hosts.forEach(host => {
38
- if (!netrc.machines[host]) netrc.machines[host] = {}
39
- netrc.machines[host].login = email
40
- netrc.machines[host].password = token
41
- })
42
- if (netrc.machines._tokens) {
43
- netrc.machines._tokens.forEach(token => {
44
- if (hosts.includes(token.host)) {
45
- token.internalWhitespace = '\n '
46
- }
47
- })
48
- }
49
- netrc.saveSync()
50
- }
51
-
52
- async function loginUserPass ({ save, expires_in: expiresIn }) {
53
- const { prompt } = require('./prompt')
54
-
55
- cli.log('Enter your Heroku credentials:')
56
- let email = await prompt('Email')
57
- let password = await prompt('Password', { hide: true })
58
-
59
- let auth
60
- try {
61
- auth = await createOAuthToken(email, password, expiresIn)
62
- } catch (err) {
63
- if (!err.body || err.body.id !== 'two_factor') throw err
64
- let secondFactor = await prompt('Two-factor code', { mask: true })
65
- auth = await createOAuthToken(email, password, expiresIn, secondFactor)
66
- }
67
- if (save) saveToken(auth)
68
- return auth
69
- }
70
-
71
- async function loginSSO ({ save, browser }) {
72
- const { prompt } = require('./prompt')
73
-
74
- let url = process.env['SSO_URL']
75
- if (!url) {
76
- let org = process.env['HEROKU_ORGANIZATION']
77
- if (!org) {
78
- org = await prompt('Enter your organization name')
79
- }
80
- url = `https://sso.heroku.com/saml/${encodeURIComponent(org)}/init?cli=true`
81
- }
82
-
83
- const open = require('./open')
84
-
85
- let openError
86
- await cli.action('Opening browser for login', open(url, browser)
87
- .catch(function (err) {
88
- openError = err
89
- })
90
- )
91
-
92
- if (openError) {
93
- cli.console.error(openError.message)
94
- }
95
-
96
- let token = await prompt('Enter your access token (typing will be hidden)', { hide: true })
97
-
98
- let account = await cli.heroku.get('/account', {
99
- headers: {
100
- Authorization: `Bearer ${token}`
101
- }
102
- })
103
-
104
- if (save) saveToken({ token, email: account.email })
105
- return { token: token, email: account.email }
106
- }
107
-
108
- async function logout () {
109
- let token = cli.heroku.options.token
110
- if (token) {
111
- // for SSO logins we delete the session since those do not show up in
112
- // authorizations because they are created a trusted client
113
- let sessionsP = cli.heroku.delete('/oauth/sessions/~')
114
- .catch(err => {
115
- if (err.statusCode === 404 && err.body && err.body.id === 'not_found' && err.body.resource === 'session') {
116
- return null
117
- }
118
- if (err.statusCode === 401 && err.body && err.body.id === 'unauthorized') {
119
- return null
120
- }
121
- throw err
122
- })
123
-
124
- // grab the default authorization because that is the token shown in the
125
- // dashboard as API Key and they may be using it for something else and we
126
- // would unwittingly break an integration that they are depending on
127
- let defaultAuthorizationP = cli.heroku.get('/oauth/authorizations/~')
128
- .catch(err => {
129
- if (err.statusCode === 404 && err.body && err.body.id === 'not_found' && err.body.resource === 'authorization') {
130
- return null
131
- }
132
- if (err.statusCode === 401 && err.body && err.body.id === 'unauthorized') {
133
- return null
134
- }
135
- throw err
136
- })
137
-
138
- // grab all the authorizations so that we can delete the token they are
139
- // using in the CLI. we have to do this rather than delete ~ because
140
- // the ~ is the API Key, not the authorization that is currently requesting
141
- let authorizationsP = cli.heroku.get('/oauth/authorizations')
142
- .catch(err => {
143
- if (err.statusCode === 401 && err.body && err.body.id === 'unauthorized') {
144
- return []
145
- }
146
- throw err
147
- })
148
-
149
- let [, defaultAuthorization, authorizations] = await Promise.all([sessionsP, defaultAuthorizationP, authorizationsP])
150
-
151
- if (accessToken(defaultAuthorization) !== token) {
152
- for (let authorization of authorizations) {
153
- if (accessToken(authorization) === token) {
154
- // remove the matching access token from core services
155
- await cli.heroku.delete(`/oauth/authorizations/${authorization.id}`)
156
- }
157
- }
158
- }
159
- }
160
-
161
- const netrc = require('netrc-parser').default
162
- netrc.loadSync()
163
- if (netrc.machines[vars.apiHost]) {
164
- netrc.machines[vars.apiHost] = undefined
165
- }
166
- if (netrc.machines[vars.httpGitHost]) {
167
- netrc.machines[vars.httpGitHost] = undefined
168
- }
169
- netrc.saveSync()
170
- }
171
-
172
- function accessToken (authorization) {
173
- return authorization && authorization.access_token && authorization.access_token.token
174
- }
175
-
176
- async function login (options = {}) {
177
- if (!options.skipLogout) await logout()
178
-
179
- try {
180
- if (options['sso']) {
181
- return await loginSSO(options)
182
- } else {
183
- return await loginUserPass(options)
184
- }
185
- } catch (e) {
186
- const { PromptMaskError } = require('./prompt')
187
- const os = require('os')
188
- if (e instanceof PromptMaskError && os.platform() === 'win32') {
189
- throw new PromptMaskError('Login is currently incompatible with git bash/Cygwin/MinGW')
190
- } else {
191
- throw e
192
- }
193
- }
194
- }
195
-
196
- function token () {
197
- const netrc = require('netrc-parser').default
198
- netrc.loadSync()
199
- if (process.env.HEROKU_API_KEY) return process.env.HEROKU_API_KEY
200
- return netrc.machines[vars.apiHost] && netrc.machines[vars.apiHost].password
201
- }
202
-
203
- module.exports = {
204
- login: login,
205
- logout: logout,
206
- token
207
- }
package/lib/command.js DELETED
@@ -1,171 +0,0 @@
1
- 'use strict'
2
-
3
- const Heroku = require('heroku-client')
4
- const cli = require('..')
5
- const auth = require('./auth')
6
- const vars = require('./vars')
7
- const Mutex = require('./mutex')
8
-
9
- function twoFactorWrapper (options, preauths, context) {
10
- return function (res, buffer) {
11
- let body
12
- try {
13
- body = this.parseBody(buffer)
14
- } catch (e) {
15
- this._handleFailure(res, buffer)
16
- }
17
-
18
- // safety check for if we have already seen this request for preauthing
19
- // this prevents an infinite loop in case some preauth fails silently
20
- // and we continue to get two_factor failures
21
-
22
- // this might be better done with a timer in case a command takes too long
23
- // and the preauthorization runs out, but that seemed unlikely
24
- if (res.statusCode === 403 && body.id === 'two_factor' && !preauths.requests.includes(this)) {
25
- let self = this
26
- // default preauth to always happen unless explicitly disabled
27
- if (options.preauth === false || !body.app) {
28
- twoFactorPrompt(options, preauths, context)
29
- .then(function (secondFactor) {
30
- self.options.headers = Object.assign({}, self.options.headers, { 'Heroku-Two-Factor-Code': secondFactor })
31
- self.request()
32
- })
33
- .catch(function (err) {
34
- self.reject(err)
35
- })
36
- } else {
37
- preauths.requests.push(self)
38
-
39
- // if multiple requests are run in parallel for the same app, we should
40
- // only preauth for the first so save the fact we already preauthed
41
- if (!preauths.promises[body.app.name]) {
42
- preauths.promises[body.app.name] = twoFactorPrompt(options, preauths, context)
43
- .then(function (secondFactor) {
44
- return cli.preauth(body.app.name, heroku(context), secondFactor)
45
- })
46
- }
47
-
48
- preauths.promises[body.app.name].then(function () {
49
- self.request()
50
- })
51
- .catch(function (err) {
52
- self.reject(err)
53
- })
54
- }
55
- } else {
56
- this._handleFailure(res, buffer)
57
- }
58
- }
59
- }
60
-
61
- function apiMiddleware (options, preauths, context) {
62
- let twoFactor = twoFactorWrapper(options, preauths, context)
63
- return function (response, cb) {
64
- let warning = response.headers['x-heroku-warning'] || response.headers['warning-message']
65
- if (warning) cli.action.warn(warning)
66
-
67
- // override the _handleFailure for this request
68
- if (!this._handleFailure) {
69
- this._handleFailure = this.handleFailure
70
- this.handleFailure = twoFactor.bind(this)
71
- }
72
-
73
- cb()
74
- }
75
- }
76
-
77
- function heroku (context, options) {
78
- let host = context.apiUrl || vars.apiUrl || 'https://api.heroku.com'
79
-
80
- let preauths = {
81
- promises: {},
82
- requests: [],
83
- twoFactorMutex: new Mutex()
84
- }
85
-
86
- let opts = {
87
- userAgent: context.version,
88
- debug: context.debug,
89
- debugHeaders: context.debugHeaders,
90
- token: context.auth ? context.auth.password : null,
91
- host: host,
92
- headers: {},
93
- rejectUnauthorized: !(process.env.HEROKU_SSL_VERIFY === 'disable' || host.endsWith('herokudev.com')),
94
- middleware: apiMiddleware(options, preauths, context)
95
- }
96
- if (process.env.HEROKU_HEADERS) {
97
- Object.assign(opts.headers, JSON.parse(process.env.HEROKU_HEADERS))
98
- }
99
- if (context.secondFactor) {
100
- Object.assign(opts.headers, { 'Heroku-Two-Factor-Code': context.secondFactor })
101
- }
102
- if (context.reason) {
103
- Object.assign(opts.headers, { 'X-Heroku-Sudo-Reason': context.reason })
104
- }
105
- cli.heroku = new Heroku(opts)
106
- return cli.heroku
107
- }
108
-
109
- let httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy
110
-
111
- function setupHttpProxy () {
112
- const url = require('url')
113
- cli.hush(`proxy set to ${httpsProxy}`)
114
- let proxy = url.parse(httpsProxy)
115
- process.env.HEROKU_HTTP_PROXY_HOST = proxy.hostname
116
- process.env.HEROKU_HTTP_PROXY_PORT = proxy.port
117
- process.env.HEROKU_HTTP_PROXY_AUTH = proxy.auth
118
- }
119
-
120
- function relogin () {
121
- if (process.env.HEROKU_LOGIN_REDIRECT === '1') return auth.login({ save: true })
122
- process.env.HEROKU_LOGIN_REDIRECT = '1'
123
- require('child_process').execSync('heroku login', { stdio: 'inherit' })
124
- return Promise.resolve()
125
- }
126
-
127
- function twoFactorPrompt (options, preauths, context) {
128
- cli.yubikey.enable()
129
- return preauths.twoFactorMutex.synchronize(function () {
130
- return cli.prompt('Two-factor code', { mask: true })
131
- .catch(function (err) {
132
- cli.yubikey.disable()
133
- throw err
134
- })
135
- .then(function (secondFactor) {
136
- cli.yubikey.disable()
137
- return secondFactor
138
- })
139
- })
140
- }
141
-
142
- function reasonPrompt (context) {
143
- return cli.prompt('Reason')
144
- .then(function (reason) {
145
- context.reason = reason
146
- })
147
- }
148
-
149
- module.exports = function command (options, fn) {
150
- return function (context) {
151
- if (typeof options === 'function') [fn, options] = [options, {}]
152
- if (httpsProxy) setupHttpProxy()
153
- cli.color.enabled = context.supportsColor
154
- let handleErr = cli.errorHandler({ debug: context.debug })
155
- let run = function () {
156
- context.auth = { password: auth.token() }
157
- let p = fn(context, heroku(context, options))
158
- if (!p.catch) return
159
- return p.catch(function (err) {
160
- if (err && err.body && err.body.id === 'unauthorized') {
161
- cli.error(err.body.message || 'Unauthorized')
162
- return relogin().then(run).catch(handleErr)
163
- } else if (err && err.body && err.body.id === 'sudo_reason_required') {
164
- cli.warn(err.body.message)
165
- return reasonPrompt(context).then(run).catch(handleErr)
166
- } else throw err
167
- }).catch(handleErr)
168
- }
169
- return run()
170
- }
171
- }
package/lib/console.js DELETED
@@ -1,105 +0,0 @@
1
- 'use strict'
2
-
3
- var cli = require('..')
4
- const stripAnsi = require('strip-ansi')
5
-
6
- var mocking
7
-
8
- function concatArguments (args) {
9
- return Array.prototype.map.call(args, function (arg) {
10
- return arg + ''
11
- }).join(' ')
12
- }
13
-
14
- /**
15
- * log is a wrapper for console.log() but can be mocked
16
- *
17
- * @param {...Object} obj - objects to be printed to stdout
18
- */
19
- function log () {
20
- if (mocking) {
21
- cli.stdout += stripAnsi(concatArguments(arguments) + '\n')
22
- } else {
23
- console.log.apply(null, arguments)
24
- }
25
- }
26
-
27
- /**
28
- * writeLog is a wrapper for process.stdout.write() but can be mocked
29
- *
30
- * @param {...Object} obj - objects to be printed to stdout
31
- */
32
- function writeLog () {
33
- if (mocking) {
34
- cli.stdout += stripAnsi(concatArguments(arguments))
35
- } else {
36
- process.stdout.write.apply(process.stdout, arguments)
37
- }
38
- }
39
-
40
- function hush () {
41
- let debug = process.env.HEROKU_DEBUG
42
- if (debug && (debug === '1' || debug.toUpperCase() === 'TRUE')) {
43
- console.error.apply(null, arguments)
44
- }
45
- }
46
-
47
- /**
48
- * error is a wrapper for console.error() but can be mocked
49
- *
50
- * @param {...Object} obj - objects to be printed to stderr
51
- */
52
- function error () {
53
- if (mocking) {
54
- cli.stderr += stripAnsi(concatArguments(arguments) + '\n')
55
- } else {
56
- console.error.apply(null, arguments)
57
- }
58
- }
59
-
60
- /**
61
- * writeError is a wrapper for process.stderr.write() but can be mocked
62
- *
63
- * @param {...Object} obj - objects to be printed to stderr
64
- */
65
- function writeError () {
66
- if (mocking) {
67
- cli.stderr += stripAnsi(concatArguments(arguments))
68
- } else {
69
- process.stderr.write.apply(process.stderr, arguments)
70
- }
71
- }
72
-
73
- /**
74
- * mock will make {@link log} and {@link error}
75
- * stop printing to stdout and stderr and start writing to the
76
- * stdout and stderr strings.
77
- */
78
- function mock (mock) {
79
- if (mock === false) {
80
- mocking = false
81
- } else {
82
- mocking = true
83
- cli.stderr = ''
84
- cli.stdout = ''
85
- }
86
- }
87
-
88
- /**
89
- * debug pretty prints an object.
90
- * It simply calls console.dir with color enabled.
91
- *
92
- * @param {Object} obj - object to be printed
93
- */
94
- function debug (obj) {
95
- console.dir(obj, { colors: true })
96
- }
97
-
98
- exports.hush = hush
99
- exports.log = log
100
- exports.writeLog = writeLog
101
- exports.error = error
102
- exports.writeError = writeError
103
- exports.mock = mock
104
- exports.mocking = () => mocking
105
- exports.debug = debug