@@ -48,7 +48,13 @@ interface CompressionItem {
48
48
* @param error Error from compressing an Item
49
49
* @param size actual size for this comparison
50
50
*/
51
- function store ( report : Report | null , context : Context , item : CompressionItem , error : Error | null , size : number ) : boolean {
51
+ function store (
52
+ report : Report | null ,
53
+ context : Context ,
54
+ item : CompressionItem ,
55
+ error : Error | null ,
56
+ size : number ,
57
+ ) : boolean {
52
58
if ( error !== null ) {
53
59
LogError ( `Could not compress '${ item . path } ' with '${ item . compression } '.` ) ;
54
60
return false ;
@@ -70,46 +76,64 @@ function store(report: Report | null, context: Context, item: CompressionItem, e
70
76
}
71
77
72
78
/**
73
- * Given a context, compress all Items within splitting work eagly per cpu core to achieve some concurrency .
74
- * @param context Finalized Valid Context from Configuration
79
+ * Compress an Item and report status to the console .
80
+ * @param item Configuration for an Item.
75
81
*/
76
- export default async function compress ( context : Context ) : Promise < boolean > {
77
- /**
78
- * Compress an Item and report status to the console.
79
- * @param item Configuration for an Item.
80
- */
81
- async function compressor ( item : CompressionItem ) : Promise < boolean > {
82
- const contents = await readFile ( item . path ) ;
83
- if ( contents ) {
84
- const buffer = Buffer . from ( contents , 'utf8' ) ;
82
+ async function compressor ( report : Report | null , context : Context , item : CompressionItem ) : Promise < boolean > {
83
+ const contents = context . fileContents . get ( item . path ) ;
84
+ if ( contents ) {
85
+ const buffer = Buffer . from ( contents , 'utf8' ) ;
85
86
86
- switch ( item . compression ) {
87
- case 'brotli' :
88
- return new Promise ( resolve =>
89
- brotliCompress ( buffer , BROTLI_OPTIONS , ( error : Error | null , result : Buffer ) =>
90
- resolve ( store ( report , context , item , error , result . byteLength ) ) ,
91
- ) ,
92
- ) ;
93
- case 'gzip' :
94
- return new Promise ( resolve =>
95
- gzip ( buffer , GZIP_OPTIONS , ( error : Error | null , result : Buffer ) => resolve ( store ( report , context , item , error , result . byteLength ) ) ) ,
96
- ) ;
97
- default :
98
- return store ( report , context , item , null , buffer . byteLength ) ;
99
- }
87
+ switch ( item . compression ) {
88
+ case 'brotli' :
89
+ return new Promise ( resolve =>
90
+ brotliCompress ( buffer , BROTLI_OPTIONS , ( error : Error | null , result : Buffer ) =>
91
+ resolve ( store ( report , context , item , error , result . byteLength ) ) ,
92
+ ) ,
93
+ ) ;
94
+ case 'gzip' :
95
+ return new Promise ( resolve =>
96
+ gzip ( buffer , GZIP_OPTIONS , ( error : Error | null , result : Buffer ) =>
97
+ resolve ( store ( report , context , item , error , result . byteLength ) ) ,
98
+ ) ,
99
+ ) ;
100
+ default :
101
+ return store ( report , context , item , null , buffer . byteLength ) ;
100
102
}
103
+ }
101
104
102
- return false ;
105
+ return false ;
106
+ }
107
+
108
+ /**
109
+ * Store the original content so it isn't retrieved from FileSystem for each compression.
110
+ * @param context
111
+ * @param path
112
+ */
113
+ async function storeOriginalFileContents ( context : Context , path : string ) : Promise < void > {
114
+ if ( ! context . fileContents . has ( path ) ) {
115
+ let content = await readFile ( path ) ;
116
+ if ( context . fileModifier !== null && content !== null ) {
117
+ content = context . fileModifier ( content ) ;
118
+ }
119
+ context . fileContents . set ( path , content || '' ) ;
103
120
}
121
+ }
104
122
105
- let report : Report | null = null ;
123
+ /**
124
+ * Find all items to compress, and store them for future compression.
125
+ * @param context
126
+ * @param findDefaultSize
127
+ */
128
+ async function findItemsToCompress ( context : Context , findDefaultSize : boolean ) : Promise < Array < CompressionItem > > {
106
129
const toCompress : Array < CompressionItem > = [ ] ;
107
130
for ( const [ path , sizeMapValue ] of context . compressed ) {
108
131
for ( let iterator : number = 0 ; iterator < OrderedCompressionValues . length ; iterator ++ ) {
109
132
const compression : Compression = OrderedCompressionValues [ iterator ] as Compression ;
110
133
const [ size , maxSize ] = sizeMapValue [ iterator ] ;
111
- if ( compression === 'none' ) {
112
- await compressor ( { path, compression, maxSize } ) ;
134
+ await storeOriginalFileContents ( context , path ) ;
135
+ if ( findDefaultSize && compression === 'none' ) {
136
+ await compressor ( null , context , { path, compression, maxSize } ) ;
113
137
}
114
138
if ( size !== undefined ) {
115
139
toCompress . push ( {
@@ -121,18 +145,35 @@ export default async function compress(context: Context): Promise<boolean> {
121
145
}
122
146
}
123
147
124
- report = stdout . isTTY && toCompress . length < 30 ? new TTYReport ( context ) : new Report ( context ) ;
148
+ return toCompress ;
149
+ }
150
+
151
+ /**
152
+ * Given a context, compress all Items within splitting work eagly per cpu core to achieve some concurrency.
153
+ * @param context Finalized Valid Context from Configuration
154
+ */
155
+ export default async function * compress ( context : Context , outputReport : boolean ) : AsyncGenerator < boolean , boolean > {
156
+ const toCompress : Array < CompressionItem > = await findItemsToCompress ( context , true ) ;
157
+ const report : Report | null = outputReport
158
+ ? null
159
+ : stdout . isTTY && toCompress . length < 30
160
+ ? new TTYReport ( context )
161
+ : new Report ( context ) ;
125
162
let success : boolean = true ;
163
+
126
164
for ( let iterator : number = 0 ; iterator < toCompress . length ; iterator += COMPRESSION_CONCURRENCY ) {
127
165
if ( iterator === 0 ) {
128
- report . update ( context ) ;
166
+ report ? .update ( context ) ;
129
167
}
130
- let itemsSuccessful = await Promise . all ( toCompress . slice ( iterator , iterator + COMPRESSION_CONCURRENCY ) . map ( compressor ) ) ;
168
+ let itemsSuccessful = await Promise . all (
169
+ toCompress . slice ( iterator , iterator + COMPRESSION_CONCURRENCY ) . map ( item => compressor ( report , context , item ) ) ,
170
+ ) ;
131
171
if ( itemsSuccessful . includes ( false ) ) {
132
172
success = false ;
133
173
}
174
+ yield success ;
134
175
}
135
176
136
- report . end ( ) ;
177
+ report ? .end ( ) ;
137
178
return success ;
138
179
}
0 commit comments