@@ -260,6 +260,7 @@ export class PublishManager {
260
260
} = options ;
261
261
262
262
const timer = new LogTimer ( 'File Serialization' ) ;
263
+ const allFiles : Record < string , FreestyleFile > = { } ;
263
264
264
265
try {
265
266
const allFilePaths = await this . collectAllFilePaths ( currentDir ) ;
@@ -274,6 +275,11 @@ export class PublishManager {
274
275
let totalProcessed = 0 ;
275
276
const totalFiles = filteredPaths . length ;
276
277
278
+ const handleAndMergeChunk : ChunkProcessor = async ( chunk , chunkInfo ) => {
279
+ Object . assign ( allFiles , chunk ) ;
280
+ await onChunkComplete ( chunk , chunkInfo ) ;
281
+ } ;
282
+
277
283
if ( textFiles . length > 0 ) {
278
284
timer . log ( `Processing ${ textFiles . length } text files` ) ;
279
285
await this . processFilesInChunks (
@@ -283,7 +289,7 @@ export class PublishManager {
283
289
batchSize ,
284
290
'text' ,
285
291
async ( chunk , chunkInfo ) => {
286
- await onChunkComplete ( chunk , chunkInfo ) ;
292
+ await handleAndMergeChunk ( chunk , chunkInfo ) ;
287
293
totalProcessed += Object . keys ( chunk ) . length ;
288
294
if ( onProgress ) {
289
295
await onProgress ( totalProcessed , totalFiles ) ;
@@ -302,7 +308,7 @@ export class PublishManager {
302
308
batchSize ,
303
309
'binary' ,
304
310
async ( chunk , chunkInfo ) => {
305
- await onChunkComplete ( chunk , chunkInfo ) ;
311
+ await handleAndMergeChunk ( chunk , chunkInfo ) ;
306
312
totalProcessed += Object . keys ( chunk ) . length ;
307
313
if ( onProgress ) {
308
314
await onProgress ( totalProcessed , totalFiles ) ;
@@ -313,8 +319,8 @@ export class PublishManager {
313
319
}
314
320
315
321
timer . log ( `Serialization completed - ${ filteredPaths . length } files processed in ${ timer . getElapsed ( ) } ms` ) ;
316
-
317
- return this . getFinalSummary ( ) ;
322
+
323
+ return allFiles ;
318
324
319
325
} catch ( error ) {
320
326
console . error ( 'Error during serialization:' , error ) ;
@@ -343,7 +349,7 @@ export class PublishManager {
343
349
344
350
console . log ( `Processing chunk ${ chunkIndex + 1 } /${ chunks . length } (${ chunk . length } files)` ) ;
345
351
346
- const chunkData = await this . processChunkWithBatching (
352
+ let chunkData : Record < string , FreestyleFile > | null = await this . processChunkWithBatching (
347
353
chunk ,
348
354
currentDir ,
349
355
batchSize ,
@@ -359,7 +365,7 @@ export class PublishManager {
359
365
360
366
console . log ( `Completed chunk ${ chunkIndex + 1 } /${ chunks . length } . Total processed: ${ ( chunkIndex + 1 ) * chunkSize } /${ filePaths . length } (${ timer . getElapsed ( ) } ms elapsed)` ) ;
361
367
362
- this . clearChunkData ( chunkData , chunk ) ;
368
+ chunkData = null ;
363
369
await this . yieldForGarbageCollection ( ) ;
364
370
}
365
371
@@ -394,7 +400,6 @@ export class PublishManager {
394
400
console . log ( `Batch ${ batchIndex } /${ totalBatches } completed (${ batch . length } files) in ${ endTime - startTime } ms` ) ;
395
401
396
402
Object . assign ( chunkData , batchResults ) ;
397
- Object . keys ( batchResults ) . forEach ( key => delete batchResults [ key ] ) ;
398
403
}
399
404
400
405
return chunkData ;
@@ -405,40 +410,31 @@ export class PublishManager {
405
410
chunkInfo : { index : number ; total : number ; filesProcessed : number ; totalFiles : number }
406
411
) : Promise < void > {
407
412
console . log ( `Processing chunk ${ chunkInfo . index + 1 } /${ chunkInfo . total } with ${ Object . keys ( chunk ) . length } files` ) ;
408
-
409
- const chunkSize = JSON . stringify ( chunk ) . length ;
410
- console . log ( `Chunk ${ chunkInfo . index + 1 } size: ${ ( chunkSize / 1024 / 1024 ) . toFixed ( 2 ) } MB` ) ;
413
+ const chunkSizeBytes = this . computeChunkSizeBytes ( chunk ) ;
414
+ console . log ( `Chunk ${ chunkInfo . index + 1 } size: ${ ( chunkSizeBytes / 1024 / 1024 ) . toFixed ( 2 ) } MB` ) ;
411
415
}
412
416
413
- private clearChunkData ( chunkData : Record < string , FreestyleFile > , filePaths : string [ ] ) : void {
414
- Object . keys ( chunkData ) . forEach ( key => {
415
- delete chunkData [ key ] ;
416
- } ) ;
417
- filePaths . length = 0 ;
418
-
419
- if ( global . gc && process . env . NODE_ENV === 'development' ) {
420
- global . gc ( ) ;
421
- }
422
- }
423
417
424
418
private async yieldForGarbageCollection ( ) : Promise < void > {
425
419
await new Promise ( resolve => setImmediate ( resolve ) ) ;
426
420
await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
427
421
}
428
422
429
- private getFinalSummary ( ) : Record < string , FreestyleFile > {
430
- return {
431
- '__summary__' : {
432
- content : JSON . stringify ( {
433
- message : 'Files processed in chunks and sent to server' ,
434
- timestamp : new Date ( ) . toISOString ( ) ,
435
- processedAt : Date . now ( )
436
- } ) ,
437
- encoding : 'utf-8' as const
423
+ private computeChunkSizeBytes ( chunk : Record < string , FreestyleFile > ) : number {
424
+ let total = 0 ;
425
+ const textEncoder = new TextEncoder ( ) ;
426
+ for ( const file of Object . values ( chunk ) ) {
427
+ const content = file . content ;
428
+ if ( file . encoding === 'base64' ) {
429
+ const len = content . length ;
430
+ const padding = content . endsWith ( '==' ) ? 2 : content . endsWith ( '=' ) ? 1 : 0 ;
431
+ total += Math . max ( 0 , Math . floor ( ( len * 3 ) / 4 ) - padding ) ;
432
+ } else {
433
+ total += textEncoder . encode ( content ) . length ;
438
434
}
439
- } ;
435
+ }
436
+ return total ;
440
437
}
441
-
442
438
private createChunks < T > ( array : T [ ] , chunkSize : number ) : T [ ] [ ] {
443
439
const chunks : T [ ] [ ] = [ ] ;
444
440
for ( let i = 0 ; i < array . length ; i += chunkSize ) {
0 commit comments