11import type { ChildProcess } from 'node:child_process' ;
22import { exec } from 'node:child_process' ;
3- import { createWriteStream } from 'node:fs' ;
43import * as fs from 'node:fs' ;
54import * as Path from 'node:path' ;
6- import { dirname , join , sep } from 'node:path' ;
5+ import { dirname , join } from 'node:path' ;
76import { promisify } from 'node:util' ;
87import { ncp } from 'ncp' ;
98import fetch from 'node-fetch' ;
@@ -333,42 +332,66 @@ export class ModLoader {
333332 openZip ( modFile , { lazyEntries : true , autoClose : true } , ( e , f ) => {
334333 if ( e ) {
335334 reject ( e ) ;
335+ } else {
336+ resolve ( f ) ;
336337 }
337- resolve ( f ) ;
338338 } ) ;
339339 } ) ;
340340
341- zipFile . readEntry ( ) ;
342- zipFile . on ( 'error' , e => process . stdout . write ( String ( e ) ) ) ;
343- zipFile . on ( 'entry' , ( entry : Entry ) => {
344- if ( entry . fileName . endsWith ( '/' ) ) {
345- // Directory
346- zipFile . readEntry ( ) ;
347- } else if ( entry . fileName . startsWith ( 'assets/' ) || entry . fileName . startsWith ( 'data/' ) ) {
348- // File
349- const prefix = entry . fileName . startsWith ( 'assets/' ) ? 7 : 5 ;
350- const targetFile = join (
351- this . path ,
352- 'mod_assets' ,
353- entry . fileName . slice ( prefix , entry . fileName . length ) ,
354- ) ;
355- const targetDir = dirname ( targetFile ) ;
356- void this . ensureDirExists ( targetDir ) . then ( ( ) => {
357- zipFile . openReadStream ( entry , ( e , readStream ) => {
358- if ( e ) {
359- throw e ;
360- }
361- readStream . pipe ( createWriteStream ( targetFile ) ) ;
362- readStream . on ( 'end' , ( ) => zipFile . readEntry ( ) ) ;
363- } ) ;
364- } ) . catch ( ( e : unknown ) => {
365- throw e ;
366- } ) ;
367- } else {
368- zipFile . readEntry ( ) ;
369- }
341+ await new Promise < void > ( ( resolve , reject ) => {
342+ let settled = false ;
343+ const settle = ( err ?: Error ) : void => {
344+ console . log ( `Settling with error: ${ err } ` ) ;
345+ if ( settled ) {
346+ return ;
347+ }
348+ settled = true ;
349+ if ( err ) {
350+ zipFile . close ( ) ;
351+ reject ( err ) ;
352+ } else {
353+ resolve ( ) ;
354+ }
355+ } ;
356+
357+ zipFile . on ( 'error' , ( err : Error ) => settle ( err ) ) ;
358+ zipFile . on ( 'end' , ( ) => settle ( ) ) ;
359+ zipFile . on ( 'entry' , ( entry : Entry ) => {
360+ console . log ( `Processing entry: ${ entry . fileName } ` ) ;
361+ if ( entry . fileName . endsWith ( '/' ) ) {
362+ // Directory
363+ zipFile . readEntry ( ) ;
364+ } else if ( entry . fileName . startsWith ( 'assets/' ) || entry . fileName . startsWith ( 'data/' ) ) {
365+ // File
366+ const prefix = entry . fileName . startsWith ( 'assets/' ) ? 7 : 5 ;
367+ const targetFile = join (
368+ this . path ,
369+ 'mod_assets' ,
370+ entry . fileName . slice ( prefix , entry . fileName . length ) ,
371+ ) ;
372+ const targetDir = dirname ( targetFile ) ;
373+ fs . promises . mkdir ( targetDir , { recursive : true } ) . then ( ( ) => {
374+ zipFile . openReadStream ( entry , ( e , readStream ) => {
375+ if ( e ) {
376+ settle ( e ) ;
377+ return ;
378+ }
379+ const chunks : Buffer [ ] = [ ] ;
380+ readStream . on ( 'data' , ( chunk : Buffer ) => chunks . push ( chunk ) ) ;
381+ readStream . on ( 'error' , ( err : Error ) => settle ( err ) ) ;
382+ readStream . on ( 'end' , ( ) => {
383+ fs . promises . writeFile ( targetFile , Buffer . concat ( chunks ) )
384+ . then ( ( ) => zipFile . readEntry ( ) )
385+ . catch ( ( err : Error ) => settle ( err ) ) ;
386+ } ) ;
387+ } ) ;
388+ } ) . catch ( ( err : Error ) => settle ( err ) ) ;
389+ } else {
390+ zipFile . readEntry ( ) ;
391+ }
392+ } ) ;
393+ zipFile . readEntry ( ) ;
370394 } ) ;
371- await new Promise ( resolve => zipFile . on ( 'end' , resolve ) ) ;
372395 }
373396
374397 /**
@@ -393,18 +416,6 @@ export class ModLoader {
393416 public async removeMods ( ) : Promise < void > {
394417 await promisify ( rimraf ) ( join ( this . path , 'mods' ) ) ;
395418 }
396-
397- protected async ensureDirExists ( path : string ) : Promise < void > {
398- const segments = path . slice ( this . path . length , this . path . length + path . length ) . split ( sep ) ;
399- for ( let i = 1 ; i <= segments . length ; i ++ ) {
400- const subPath = join ( this . path , segments . slice ( 0 , i ) . join ( sep ) ) ;
401- try {
402- await fs . promises . stat ( subPath ) ;
403- } catch {
404- await fs . promises . mkdir ( subPath ) ;
405- }
406- }
407- }
408419}
409420
410421export interface IModLoaderArgs {
0 commit comments