@heroku/heroku-cli-util 8.0.15 → 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/lib/mutex.js DELETED
@@ -1,41 +0,0 @@
1
- 'use strict'
2
-
3
- // Adapted from https://blog.jcoglan.com/2016/07/12/mutexes-and-javascript/
4
-
5
- let Mutex = function () {
6
- this._busy = false
7
- this._queue = []
8
- }
9
-
10
- Mutex.prototype.synchronize = function (task) {
11
- let self = this
12
-
13
- return new Promise(function (resolve, reject) {
14
- self._queue.push([task, resolve, reject])
15
- if (!self._busy) {
16
- self._dequeue()
17
- }
18
- })
19
- }
20
-
21
- Mutex.prototype._dequeue = function () {
22
- this._busy = true
23
- let next = this._queue.shift()
24
-
25
- if (next) {
26
- this._execute(next)
27
- } else {
28
- this._busy = false
29
- }
30
- }
31
-
32
- Mutex.prototype._execute = function (record) {
33
- let [task, resolve, reject] = record
34
- let self = this
35
-
36
- task().then(resolve, reject).then(function () {
37
- self._dequeue()
38
- })
39
- }
40
-
41
- module.exports = Mutex
package/lib/open.js DELETED
@@ -1,22 +0,0 @@
1
- 'use strict'
2
-
3
- let { color } = require('..')
4
-
5
- function open (url, browser) {
6
- let opn = require('opn')
7
- return new Promise((resolve, reject) => {
8
- let opts = { wait: false }
9
- if (browser) { opts.app = browser }
10
- opn(url, opts, err => {
11
- if (err) {
12
- reject(new Error(
13
- `Error opening web browser.
14
- ${err}
15
-
16
- Manually visit ${color.cyan(url)} in your browser.`))
17
- } else resolve(err)
18
- })
19
- })
20
- }
21
-
22
- module.exports = open
package/lib/preauth.js DELETED
@@ -1,26 +0,0 @@
1
- 'use strict'
2
- let util = require('./util')
3
-
4
- /**
5
- * preauth will make an API call to preauth a user for an app
6
- * this makes it so the user will not have to enter a 2fa code
7
- * for the next few minutes on the specified app.
8
- *
9
- * You need this if your command is going to make multiple API calls
10
- * since otherwise the secondFactor key would only work one time for
11
- * yubikeys.
12
- *
13
- * @param {String} app the app to preauth against
14
- * @param {Heroku} heroku a heroku api client
15
- * @param {String} secondFactor a second factor code
16
- * @return {Promise} A promise fulfilled when the preauth is complete
17
- */
18
- function preauth (app, heroku, secondFactor) {
19
- return heroku.request({
20
- method: 'PUT',
21
- path: `/apps/${app}/pre-authorizations`,
22
- headers: { 'Heroku-Two-Factor-Code': secondFactor }
23
- })
24
- }
25
-
26
- module.exports = util.promiseOrCallback(preauth)
package/lib/process.js DELETED
@@ -1,14 +0,0 @@
1
- function Process () {
2
- this.env = process.env
3
- }
4
- Process.prototype.mock = function () {
5
- this.mocking = true
6
- }
7
- Process.prototype.exit = function (code) {
8
- if (this.mocking) {
9
- this.exitCode = code
10
- } else {
11
- process.exit(code)
12
- }
13
- }
14
- module.exports = new Process()
package/lib/prompt.js DELETED
@@ -1,150 +0,0 @@
1
- 'use strict'
2
-
3
- const cli = require('../')
4
- const errors = require('./errors')
5
- const util = require('./util')
6
- const color = cli.color
7
- const ansi = require('ansi-escapes')
8
- const Spinner = require('./spinner')
9
- const nodeUtil = require('util')
10
-
11
- function promptMasked (options) {
12
- return new Promise(function (resolve, reject) {
13
- let stdin = process.stdin
14
- let stderr = process.stderr
15
- let input = ''
16
- stdin.setEncoding('utf8')
17
- stderr.write(ansi.eraseLine)
18
- stderr.write(ansi.cursorLeft)
19
- cli.console.writeError(options.prompt)
20
- stdin.resume()
21
- stdin.setRawMode(true)
22
-
23
- function stop () {
24
- if (!options.hide) {
25
- stderr.write(
26
- ansi.cursorHide +
27
- ansi.cursorLeft +
28
- options.prompt +
29
- input.replace(/./g, '*') +
30
- '\n' +
31
- ansi.cursorShow)
32
- } else {
33
- stderr.write('\n')
34
- }
35
- stdin.removeListener('data', fn)
36
- stdin.setRawMode(false)
37
- stdin.pause()
38
- }
39
-
40
- function enter () {
41
- if (input.length === 0) return
42
- stop()
43
- resolve(input)
44
- }
45
-
46
- function ctrlc () {
47
- reject(new Error(''))
48
- stop()
49
- }
50
-
51
- function backspace () {
52
- if (input.length === 0) return
53
- input = input.substr(0, input.length - 1)
54
- stderr.write(ansi.cursorBackward(1))
55
- stderr.write(ansi.eraseEndLine)
56
- }
57
-
58
- function newchar (c) {
59
- input += c
60
- stderr.write(options.hide ? '*'.repeat(c.length) : c)
61
- }
62
-
63
- let fn = function (c) {
64
- switch (c) {
65
- case '\u0004': // Ctrl-d
66
- case '\r':
67
- case '\n':
68
- return enter()
69
- case '\u0003': // Ctrl-c
70
- return ctrlc()
71
- default:
72
- // backspace
73
- if (c.charCodeAt(0) === 127) return backspace()
74
- else return newchar(c)
75
- }
76
- }
77
- stdin.on('data', fn)
78
- })
79
- }
80
-
81
- function PromptMaskError (message) {
82
- Error.call(this)
83
- Error.captureStackTrace(this, this.constructor)
84
- this.name = this.constructor.name
85
- this.message = message
86
- }
87
-
88
- nodeUtil.inherits(PromptMaskError, Error)
89
-
90
- exports.PromptMaskError = PromptMaskError
91
-
92
- function prompt (name, options) {
93
- options = options || {}
94
- options.name = name
95
- options.prompt = name ? color.dim(`${name}: `) : color.dim('> ')
96
- let isTTY = process.env.TERM !== 'dumb' && process.stdin.isTTY
97
- let spinnerTask
98
- if (options.mask || options.hide) {
99
- if (!isTTY) {
100
- return Promise.reject(new PromptMaskError(`CLI needs to prompt for ${options.name || options.prompt} but stdin is not a tty.`))
101
- }
102
-
103
- spinnerTask = function () {
104
- return promptMasked(options)
105
- }
106
- } else {
107
- spinnerTask = function () {
108
- return new Promise(function (resolve) {
109
- process.stdin.setEncoding('utf8')
110
- cli.console.writeError(options.prompt)
111
- process.stdin.resume()
112
- process.stdin.once('data', function (data) {
113
- process.stdin.pause()
114
- data = data.trim()
115
- if (data === '') {
116
- resolve(prompt(name))
117
- } else {
118
- resolve(data)
119
- }
120
- })
121
- })
122
- }
123
- }
124
- return Spinner.prompt(spinnerTask)
125
- }
126
-
127
- function confirmApp (app, confirm, message) {
128
- return new Promise(function (resolve, reject) {
129
- if (confirm) {
130
- if (confirm === app) return resolve()
131
- return reject(new Error(`Confirmation ${cli.color.bold.red(confirm)} did not match ${cli.color.bold.red(app)}. Aborted.`))
132
- }
133
- if (!message) {
134
- message = `WARNING: Destructive Action
135
- This command will affect the app ${cli.color.bold.red(app)}`
136
- }
137
- errors.warn(message)
138
- errors.warn(`To proceed, type ${cli.color.bold.red(app)} or re-run this command with ${cli.color.bold.red('--confirm', app)}`)
139
- console.error()
140
- prompt().then(function (confirm) {
141
- if (confirm === app) {
142
- return resolve()
143
- }
144
- return reject(new Error(`Confirmation did not match ${cli.color.bold.red(app)}. Aborted.`))
145
- })
146
- })
147
- }
148
-
149
- exports.prompt = util.promiseOrCallback(prompt)
150
- exports.confirmApp = util.promiseOrCallback(confirmApp)
package/lib/spinner.js DELETED
@@ -1,147 +0,0 @@
1
- 'use strict'
2
-
3
- // code mostly from https://github.com/sindresorhus/ora
4
-
5
- const stripAnsi = require('strip-ansi')
6
- let console = require('./console')
7
- let color = require('@heroku-cli/color').default
8
- let errors = require('./errors')
9
-
10
- class Spinner {
11
- constructor (options) {
12
- this.options = Object.assign({
13
- text: ''
14
- }, options)
15
-
16
- this.ansi = require('ansi-escapes')
17
- let spinners = require('./spinners.json')
18
-
19
- this.color = this.options.color || 'heroku'
20
- this.spinner = process.platform === 'win32' ? spinners.line : (this.options.spinner ? spinners[this.options.spinner] : spinners.dots2)
21
- this.text = this.options.text
22
- this.interval = this.options.interval || this.spinner.interval || 100
23
- this.id = null
24
- this.frameIndex = 0
25
- this.stream = this.options.stream || process.stderr
26
- this.enabled = !console.mocking() && (this.stream && this.stream.isTTY) && !process.env.CI && !['dumb', 'emacs-color'].includes(process.env.TERM)
27
- this.warnings = []
28
- }
29
-
30
- start () {
31
- if (this.id) return
32
- if (!this.enabled) {
33
- console.writeError(this.text)
34
- return
35
- }
36
-
37
- this.stream.write(this.ansi.cursorLeft)
38
- this.stream.write(this.ansi.eraseLine)
39
- this.stream.write(this.ansi.cursorHide)
40
- this._render()
41
- this.id = setInterval(this._spin.bind(this), this.interval)
42
- process.on('SIGWINCH', this._sigwinch = this._render.bind(this))
43
- }
44
-
45
- stop (status) {
46
- if (status && !this.enabled) console.error(` ${status}`)
47
- if (!this.enabled) return
48
- if (status) this._status = status
49
-
50
- process.removeListener('SIGWINCH', this._sigwinch)
51
- clearInterval(this.id)
52
- this.id = null
53
- this.enabled = false
54
- this.frameIndex = 0
55
- this._render()
56
- this.stream.write(this.ansi.cursorShow)
57
- }
58
-
59
- warn (msg) {
60
- if (!this.enabled) {
61
- console.writeError(color.yellow(' !') + '\n' + errors.renderWarning(msg) + '\n' + this.text)
62
- } else {
63
- this.warnings.push(msg)
64
- this._render()
65
- }
66
- }
67
-
68
- get status () {
69
- return this._status
70
- }
71
-
72
- set status (status) {
73
- this._status = status
74
- if (this.enabled) this._render()
75
- else console.writeError(` ${this.status}\n${this.text}`)
76
- }
77
-
78
- clear () {
79
- if (!this._output) return
80
- this.stream.write(this.ansi.cursorUp(this._lines(this._output)))
81
- this.stream.write(this.ansi.eraseDown)
82
- }
83
-
84
- _render () {
85
- if (this._output) this.clear()
86
- this._output = `${this.text}${this.enabled ? ' ' + this._frame() : ''} ${this.status ? this.status : ''}\n` +
87
- this.warnings.map(w => errors.renderWarning(w) + '\n').join('')
88
- this.stream.write(this._output)
89
- }
90
-
91
- _lines (s) {
92
- return stripAnsi(s)
93
- .split('\n')
94
- .map(l => Math.ceil(l.length / this._width))
95
- .reduce((c, i) => c + i, 0)
96
- }
97
-
98
- get _width () {
99
- return errors.errtermwidth()
100
- }
101
-
102
- _spin () {
103
- if (Spinner.prompts.length > 0) {
104
- return
105
- }
106
-
107
- this.stream.write(this.ansi.cursorUp(this._lines(this._output)))
108
- let y = this._lines(this.text) - 1
109
- let lastline = stripAnsi(this.text).split('\n').pop()
110
- let x = 1 + lastline.length - (this._lines(lastline) - 1) * this._width
111
- this.stream.write(this.ansi.cursorMove(x, y))
112
- this.stream.write(this._frame())
113
- this.stream.write(this.ansi.cursorDown(this._lines(this._output) - y))
114
- this.stream.write(this.ansi.cursorLeft)
115
- this.stream.write(this.ansi.eraseLine)
116
- }
117
-
118
- _frame () {
119
- var frames = this.spinner.frames
120
- var frame = frames[this.frameIndex]
121
- if (this.color) frame = color[this.color](frame)
122
- this.frameIndex = ++this.frameIndex % frames.length
123
- return frame
124
- }
125
-
126
- static prompt (promptFn) {
127
- let removeFn = function () {
128
- Spinner.prompts = Spinner.prompts.filter(p => p !== promptFn)
129
- }
130
-
131
- Spinner.prompts.push(promptFn)
132
-
133
- return promptFn()
134
- .then(data => {
135
- removeFn()
136
- return data
137
- })
138
- .catch(err => {
139
- removeFn()
140
- throw err
141
- })
142
- }
143
- }
144
-
145
- Spinner.prompts = []
146
-
147
- module.exports = Spinner