@@ -2,25 +2,26 @@ import process from 'node:process';
2
2
3
3
type LogMsg = string ;
4
4
type LogType = 'error' | 'log' | 'warn' ;
5
- type FileLog = { msg : LogMsg ; type : LogType } ;
5
+ type FileLog = { msg : LogMsg ; type : LogType ; codemodName : string } ;
6
6
type Source = URL [ 'pathname' ] ;
7
7
8
- let codemodName = 'nodjs-codemod' ;
8
+ let defaultCodemodName = 'nodjs-codemod' ;
9
9
10
10
/**
11
- * Set the codemod name for logging output
11
+ * Set the default codemod name for logging output
12
12
*/
13
13
export const setCodemodName = ( name : string ) => {
14
- codemodName = name ;
14
+ defaultCodemodName = name ;
15
15
} ;
16
16
17
17
/**
18
18
* Collect log entries and report them at the end, collated by source module.
19
19
*/
20
- export const logger = ( source : Source , type : LogType , msg : LogMsg ) => {
20
+ export const logger = ( source : Source , type : LogType , msg : LogMsg , codemodName ?: string ) => {
21
+ const name = codemodName ?? defaultCodemodName ;
21
22
const fileLog = new Set < FileLog > ( logs . has ( source ) ? logs . get ( source ) : [ ] ) ;
22
23
23
- fileLog . add ( { msg, type } ) ;
24
+ fileLog . add ( { msg, type, codemodName : name } ) ;
24
25
logs . set ( source , fileLog ) ;
25
26
} ;
26
27
@@ -34,19 +35,45 @@ process.once('beforeExit', emitLogs);
34
35
function emitLogs ( ) {
35
36
let hasError = false ;
36
37
37
- for ( const [ sourceFile , fileLog ] of logs . entries ( ) ) {
38
- console . log ( `[Codemod: ${ codemodName } ]:` , sourceFile ) ;
39
- for ( const { msg, type } of fileLog ) {
40
- console [ type ] ( ' •' , msg ) ;
41
- if ( type === 'error' ) hasError = true ;
38
+ // Group logs by codemod name first, then by source file
39
+ const logsByCodemod = new Map < string , Map < Source , Set < FileLog > > > ( ) ;
40
+
41
+ for ( const [ sourceFile , fileLogs ] of logs . entries ( ) ) {
42
+ for ( const fileLog of fileLogs ) {
43
+ if ( ! logsByCodemod . has ( fileLog . codemodName ) ) {
44
+ logsByCodemod . set ( fileLog . codemodName , new Map ( ) ) ;
45
+ }
46
+ const codemodLogs = logsByCodemod . get ( fileLog . codemodName ) ! ;
47
+ if ( ! codemodLogs . has ( sourceFile ) ) {
48
+ codemodLogs . set ( sourceFile , new Set ( ) ) ;
49
+ }
50
+ codemodLogs . get ( sourceFile ) ! . add ( fileLog ) ;
42
51
}
43
52
}
44
53
45
- if ( hasError ) {
46
- console . error ( `[Codemod: ${ codemodName } ]: migration incomplete!` ) ;
47
- process . exitCode = 1 ;
48
- } else {
49
- process . exitCode = 0 ;
50
- console . log ( `[Codemod: ${ codemodName } ]: migration complete!` ) ;
54
+ for ( const [ codemodName , codemodLogs ] of logsByCodemod . entries ( ) ) {
55
+ for ( const [ sourceFile , fileLogs ] of codemodLogs . entries ( ) ) {
56
+ console . log ( `[Codemod: ${ codemodName } ]:` , sourceFile ) ;
57
+ for ( const { msg, type } of fileLogs ) {
58
+ console [ type ] ( ' •' , msg ) ;
59
+ if ( type === 'error' ) hasError = true ;
60
+ }
61
+ }
62
+
63
+ if ( hasError ) {
64
+ console . error ( `[Codemod: ${ codemodName } ]: migration incomplete!` ) ;
65
+ } else {
66
+ console . log ( `[Codemod: ${ codemodName } ]: migration complete!` ) ;
67
+ }
68
+ hasError = false ; // Reset for next codemod
51
69
}
70
+
71
+ // Set overall exit code based on any errors
72
+ process . exitCode = Array . from ( logsByCodemod . values ( ) )
73
+ . some ( codemodLogs =>
74
+ Array . from ( codemodLogs . values ( ) )
75
+ . some ( fileLogs =>
76
+ Array . from ( fileLogs ) . some ( log => log . type === 'error' )
77
+ )
78
+ ) ? 1 : 0 ;
52
79
}
0 commit comments