/
index.ts
160 lines (139 loc) · 3.36 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import * as Errors from '../errors'
import * as util from 'util'
import {ActionBase} from './action/base'
import {config, Config} from './config'
import deps from './deps'
import {ExitError} from './exit'
import {IPromptOptions} from './prompt'
import * as Table from './styled/table'
const hyperlinker = require('hyperlinker')
function timeout(p: Promise<any>, ms: number) {
function wait(ms: number, unref = false) {
return new Promise(resolve => {
const t: any = setTimeout(() => resolve(null), ms)
if (unref) t.unref()
})
}
return Promise.race([p, wait(ms, true).then(() => ux.error('timed out'))])
}
async function flush() {
const p = new Promise(resolve => {
process.stdout.once('drain', () => resolve(null))
})
const flushed = process.stdout.write('')
if (flushed) {
return Promise.resolve()
}
return p
}
export const ux = {
config,
warn: Errors.warn,
error: Errors.error,
exit: Errors.exit,
get prompt() {
return deps.prompt.prompt
},
/**
* "press anykey to continue"
*/
get anykey() {
return deps.prompt.anykey
},
get confirm() {
return deps.prompt.confirm
},
get action() {
return config.action
},
get prideAction() {
return config.prideAction
},
styledObject(obj: any, keys?: string[]) {
ux.info(deps.styledObject(obj, keys))
},
get styledHeader() {
return deps.styledHeader
},
get styledJSON() {
return deps.styledJSON
},
get table() {
return deps.table
},
get tree() {
return deps.tree
},
get open() {
return deps.open
},
get wait() {
return deps.wait
},
get progress() {
return deps.progress
},
async done() {
config.action.stop()
// await flushStdout()
},
trace(format: string, ...args: string[]) {
if (this.config.outputLevel === 'trace') {
process.stdout.write(util.format(format, ...args) + '\n')
}
},
debug(format: string, ...args: string[]) {
if (['trace', 'debug'].includes(this.config.outputLevel)) {
process.stdout.write(util.format(format, ...args) + '\n')
}
},
info(format: string, ...args: string[]) {
process.stdout.write(util.format(format, ...args) + '\n')
},
log(format?: string, ...args: string[]) {
this.info(format || '', ...args)
},
url(text: string, uri: string, params = {}) {
const supports = require('supports-hyperlinks')
if (supports.stdout) {
this.log(hyperlinker(text, uri, params))
} else {
this.log(uri)
}
},
annotation(text: string, annotation: string) {
const supports = require('supports-hyperlinks')
if (supports.stdout) {
// \u001b]8;;https://google.com\u0007sometext\u001b]8;;\u0007
this.log(`\u001B]1337;AddAnnotation=${text.length}|${annotation}\u0007${text}`)
} else {
this.log(text)
}
},
async flush() {
await timeout(flush(), 10_000)
},
}
export {
config,
ActionBase,
Config,
ExitError,
IPromptOptions,
Table,
}
const cliuxProcessExitHandler = async () => {
try {
await ux.done()
} catch (error) {
// tslint:disable no-console
console.error(error)
process.exitCode = 1
}
}
// to avoid MaxListenersExceededWarning
// only attach named listener once
const cliuxListener = process.listeners('exit').find(fn => fn.name === cliuxProcessExitHandler.name)
if (!cliuxListener) {
process.once('exit', cliuxProcessExitHandler)
}