11const proggy = require ( 'proggy' )
2- const { log } = require ( 'proc-log' )
2+ const { log, output } = require ( 'proc-log' )
33const { explain } = require ( './explain-eresolve.js' )
44const { formatWithOptions } = require ( './format' )
55
@@ -17,7 +17,13 @@ const COLOR_PALETTE = ({ chalk: c }) => ({
1717 silly : c . inverse ,
1818} )
1919
20- const LEVELS = log . LEVELS . reduce ( ( acc , key ) => {
20+ const LOG_LEVELS = log . LEVELS . reduce ( ( acc , key ) => {
21+ acc [ key ] = key
22+ return acc
23+ } , { } )
24+
25+ // TODO: move flush to proc-log
26+ const OUTPUT_LEVELS = [ 'flush' , ...output . LEVELS ] . reduce ( ( acc , key ) => {
2127 acc [ key ] = key
2228 return acc
2329} , { } )
@@ -55,20 +61,20 @@ const LEVEL_OPTIONS = {
5561
5662const LEVEL_METHODS = {
5763 ...LEVEL_OPTIONS ,
58- [ LEVELS . timing ] : {
64+ [ LOG_LEVELS . timing ] : {
5965 show : ( { timing, index } ) => ! ! timing && index !== 0 ,
6066 } ,
6167}
6268
63- const safeJsonParse = ( maybeJsonStr ) => {
64- if ( typeof maybeJsonStr !== 'string' ) {
65- return maybeJsonStr
66- }
67- try {
68- return JSON . parse ( maybeJsonStr )
69- } catch {
70- return { }
69+ const tryJsonParse = ( value ) => {
70+ if ( typeof value === 'string' ) {
71+ try {
72+ return JSON . parse ( value )
73+ } catch {
74+ return { }
75+ }
7176 }
77+ return value
7278}
7379
7480const setBlocking = ( stream ) => {
@@ -122,6 +128,7 @@ class Display {
122128 constructor ( { stdout, stderr } ) {
123129 this . #stdout = setBlocking ( stdout )
124130 this . #stderr = setBlocking ( stderr )
131+
125132 // Handlers are set immediately so they can buffer all events
126133 process . on ( 'log' , this . #logHandler)
127134 process . on ( 'output' , this . #outputHandler)
@@ -174,21 +181,34 @@ class Display {
174181 log . resume ( )
175182
176183 // TODO: this should be a proc-log method `proc-log.output.flush`?
177- this . #outputHandler( ' flush' )
184+ this . #outputHandler( OUTPUT_LEVELS . flush )
178185
179186 this . #startProgress( { progress, unicode } )
180187 }
181188
189+ // STREAM WRITES
190+
191+ // Write formatted and (non-)colorized output to streams
192+ #stdoutWrite ( options , ...args ) {
193+ this . #stdout. write ( formatWithOptions ( { colors : this . #stdoutColor, ...options } , ...args ) )
194+ }
195+
196+ #stderrWrite ( options , ...args ) {
197+ this . #stderr. write ( formatWithOptions ( { colors : this . #stderrColor, ...options } , ...args ) )
198+ }
199+
200+ // HANDLERS
201+
182202 // Public class field so it can be passed directly as a listener
183203 #logHandler = ( ...args ) => {
184- if ( args [ 0 ] === LEVELS . resume ) {
204+ if ( args [ 0 ] === LOG_LEVELS . resume ) {
185205 this . #logState. buffering = false
186206 this . #logState. buffer . forEach ( ( item ) => this . #tryWriteLog( ...item ) )
187207 this . #logState. buffer . length = 0
188208 return
189209 }
190210
191- if ( args [ 0 ] === LEVELS . pause ) {
211+ if ( args [ 0 ] === LOG_LEVELS . pause ) {
192212 this . #logState. buffering = true
193213 return
194214 }
@@ -203,23 +223,22 @@ class Display {
203223
204224 // Public class field so it can be passed directly as a listener
205225 #outputHandler = ( ...args ) => {
206- if ( args [ 0 ] === ' flush' ) {
226+ if ( args [ 0 ] === OUTPUT_LEVELS . flush ) {
207227 this . #outputState. buffering = false
208228 if ( args [ 1 ] && this . #json) {
209- const mergedJsonOutput = { }
210- for ( const [ , ... items ] of this . #outputState. buffer ) {
211- Object . assign ( mergedJsonOutput , ... items . map ( safeJsonParse ) )
229+ const json = { }
230+ for ( const [ , item ] of this . #outputState. buffer ) {
231+ Object . assign ( json , tryJsonParse ( item ) )
212232 }
213- Object . assign ( args [ 1 ] )
214- this . #writeOutput( 'standard' , JSON . stringify ( mergedJsonOutput , null , 2 ) )
233+ this . #writeOutput( 'standard' , JSON . stringify ( { ...json , ...args [ 1 ] } , null , 2 ) )
215234 } else {
216235 this . #outputState. buffer . forEach ( ( item ) => this . #writeOutput( ...item ) )
217236 }
218237 this . #outputState. buffer . length = 0
219238 return
220239 }
221240
222- if ( args [ 0 ] === ' buffer' ) {
241+ if ( args [ 0 ] === OUTPUT_LEVELS . buffer ) {
223242 this . #outputState. buffer . push ( [ 'standard' , ...args . slice ( 1 ) ] )
224243 return
225244 }
@@ -237,25 +256,27 @@ class Display {
237256 #writeOutput ( ...args ) {
238257 const { level } = getLevel ( args . shift ( ) )
239258
240- if ( level === ' standard' ) {
241- this . #stdout . write ( formatWithOptions ( { colors : this . #stdoutColor } , ...args ) )
259+ if ( level === OUTPUT_LEVELS . standard ) {
260+ this . #stdoutWrite ( { } , ...args )
242261 return
243262 }
244263
245- if ( level === ' error' ) {
246- this . #stderr . write ( formatWithOptions ( { colors : this . #stderrColor } , ...args ) )
264+ if ( level === OUTPUT_LEVELS . error ) {
265+ this . #stderrWrite ( { } , ...args )
247266 }
248267 }
249268
250269 // TODO: move this to proc-log and remove this public method
251270 flushOutput ( jsonError ) {
252- this . #outputHandler( ' flush' , jsonError )
271+ this . #outputHandler( OUTPUT_LEVELS . flush , jsonError )
253272 }
254273
255274 // LOGS
256275
276+ // TODO: make proc-log able to send signal data like `force`
277+ // when that happens, remove this public method
257278 forceLog ( level , ...args ) {
258- // This will show the log regardless of the current loglevel
279+ // This will show the log regardless of the current loglevel except when silent
259280 if ( this . #levelIndex !== 0 ) {
260281 this . #logHandler( { level, force : true } , ...args )
261282 }
@@ -269,7 +290,7 @@ class Display {
269290 // highly abbreviated explanation of what's being overridden.
270291 // TODO: this could probably be moved to arborist now that display is refactored
271292 const [ level , heading , message , expl ] = args
272- if ( level === LEVELS . warn && heading === 'ERESOLVE' && expl && typeof expl === 'object' ) {
293+ if ( level === LOG_LEVELS . warn && heading === 'ERESOLVE' && expl && typeof expl === 'object' ) {
273294 this . #writeLog( level , heading , message )
274295 this . #writeLog( level , '' , explain ( expl , this . #stderrChalk, 2 ) )
275296 return
@@ -278,9 +299,10 @@ class Display {
278299 } catch ( ex ) {
279300 try {
280301 // if it crashed once, it might again!
281- this . #writeLog( LEVELS . verbose , null , `attempt to log crashed` , ...args , ex )
302+ this . #writeLog( LOG_LEVELS . verbose , null , `attempt to log crashed` , ...args , ex )
282303 } catch ( ex2 ) {
283- /* istanbul ignore next - this happens if the object has an inspect method that crashes */
304+ // This happens if the object has an inspect method that crashes so just console.error
305+ // with the errors but don't do anything else that might error again.
284306 // eslint-disable-next-line no-console
285307 console . error ( `attempt to log crashed` , ex , ex2 )
286308 }
@@ -301,7 +323,7 @@ class Display {
301323 this . #logColors[ level ] ( levelOpts . label ?? level ) ,
302324 title ? this . #logColors. title ( title ) : null ,
303325 ]
304- this . #stderr . write ( formatWithOptions ( { prefix, colors : this . stderrColor } , ...args ) )
326+ this . #stderrWrite ( { prefix } , ...args )
305327 } else if ( this . #progress) {
306328 // TODO: make this display a single log line of filtered messages
307329 }
0 commit comments