1 | 'use strict'
|
2 |
|
3 | const stripAnsi = require('strip-ansi')
|
4 | let cli = require('..')
|
5 | let console = require('./console')
|
6 | let linewrap = require('./linewrap')
|
7 | let path = require('path')
|
8 | let os = require('os')
|
9 |
|
10 | function errtermwidth () {
|
11 | if (global.columns) return global.columns
|
12 | if (!process.stderr.isTTY || !process.stderr.getWindowSize) return 80
|
13 | let width = process.stderr.getWindowSize()[0]
|
14 | return width < 30 ? 30 : width
|
15 | }
|
16 |
|
17 | function wrap (msg) {
|
18 | return linewrap(6,
|
19 | errtermwidth(), {
|
20 | skipScheme: 'ansi-color',
|
21 | skip: /^\$ .*$/
|
22 | })(msg || '')
|
23 | }
|
24 |
|
25 | function bangify (msg, c) {
|
26 | let lines = msg.split('\n')
|
27 | for (let i = 0; i < lines.length; i++) {
|
28 | let line = lines[i]
|
29 | lines[i] = ' ' + c + line.substr(2, line.length)
|
30 | }
|
31 | return lines.join('\n')
|
32 | }
|
33 |
|
34 | function getErrorMessage (err) {
|
35 | if (err.body) {
|
36 |
|
37 | if (err.body.message) {
|
38 | return err.body.message
|
39 | } else if (err.body.error) {
|
40 | return err.body.error
|
41 | }
|
42 | }
|
43 |
|
44 | if (err.message && err.code) {
|
45 | return `${err.code}: ${err.message}`
|
46 | } else if (err.message) {
|
47 | return err.message
|
48 | }
|
49 | return err
|
50 | }
|
51 |
|
52 | let arrow = process.platform === 'win32' ? '!' : '▸'
|
53 |
|
54 | function error (err) {
|
55 | console.error(bangify(wrap(getErrorMessage(err)), cli.color.red(arrow)))
|
56 | }
|
57 |
|
58 | function warn (msg) {
|
59 | console.error(renderWarning(msg))
|
60 | }
|
61 |
|
62 | function renderWarning (msg) {
|
63 | return bangify(wrap(msg), cli.color.yellow(arrow))
|
64 | }
|
65 |
|
66 | function logtimestamp () {
|
67 | return new Date().toISOString()
|
68 | .replace(/T/, ' ')
|
69 | .replace(/-/g, '/')
|
70 | .replace(/\..+/, '')
|
71 | }
|
72 |
|
73 | function cacheHome () {
|
74 | let base
|
75 | if (process.env.XDG_CACHE_HOME) base = process.env.XDG_CACHE_HOME
|
76 | if (!base) {
|
77 | if (process.platform === 'darwin') {
|
78 | base = path.join(os.homedir(), 'Library', 'Caches')
|
79 | } else if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
|
80 | base = process.env.LOCALAPPDATA
|
81 | } else {
|
82 | base = path.join(os.homedir(), '.cache')
|
83 | }
|
84 | }
|
85 | return path.join(base, 'heroku')
|
86 | }
|
87 |
|
88 | function log (msg) {
|
89 | let fs = require('fs')
|
90 | let logPath = path.join(cacheHome(), 'error.log')
|
91 | fs.appendFileSync(logPath, logtimestamp() + ' ' + stripAnsi(msg) + '\n')
|
92 | }
|
93 |
|
94 | function errorHandler (options) {
|
95 | options = options || {}
|
96 | function exit () {
|
97 | if (options.exit !== false) {
|
98 | process.exit(1)
|
99 | }
|
100 | }
|
101 | return function handleErr (err) {
|
102 | if (cli.raiseErrors) throw err
|
103 | try {
|
104 | if (err !== '') error(err)
|
105 | if (err.stack) {
|
106 | log(err.stack)
|
107 | if (options.debug) console.error(err.stack)
|
108 | }
|
109 | if (err.body) log(JSON.stringify(err.body))
|
110 | exit()
|
111 | } catch (err) {
|
112 | console.error(err.stack)
|
113 | process.exit(-1)
|
114 | }
|
115 | }
|
116 | }
|
117 |
|
118 | module.exports.error = error
|
119 | module.exports.warn = warn
|
120 | module.exports.errorHandler = errorHandler
|
121 | module.exports.renderWarning = renderWarning
|
122 | module.exports.errtermwidth = errtermwidth
|