1- import * as fs from 'fs/promises' ;
2- import * as fs1 from 'fs' ;
1+ import * as fsPromises from 'fs/promises' ;
2+ import * as fs from 'fs' ;
33import * as path from 'path' ;
44import * as tar from 'tar' ;
55import axios from 'axios' ;
66import * as unzipper from 'unzipper' ;
7- import { Semaphore } from 'async-mutex' ;
7+ import { Semaphore } from 'async-mutex' ;
88import * as os from "os" ;
99import { logger } from "../wrapper/loggerConfig" ;
10+ import { finished } from 'stream/promises' ;
1011
12+ type SupportedPlatforms = 'win32' | 'darwin' | 'linux' ;
1113export class CxInstaller {
1214 private readonly platform : string ;
1315 private cliVersion : string ;
1416 private readonly resourceDirPath : string ;
17+ private readonly cliDefaultVersion = '2.2.5' ; // This will be used if the version file is not found. Should be updated with the latest version.
1518 private static installSemaphore = new Semaphore ( 1 ) ; // Semaphore with 1 slot
1619
1720 constructor ( platform : string ) {
1821 this . platform = platform ;
1922 this . resourceDirPath = path . join ( __dirname , `../wrapper/resources` ) ;
2023 }
2124
22- // Method to get the download URL based on OS and architecture
2325 async getDownloadURL ( ) : Promise < string > {
2426 const cliVersion = await this . readASTCLIVersion ( ) ;
25- let platformString : string ;
26- let archiveExtension : string ;
27-
28- switch ( this . platform ) {
29- case 'win32' :
30- platformString = 'windows' ;
31- archiveExtension = 'zip' ;
32- break ;
33- case 'darwin' :
34- archiveExtension = 'tar.gz' ;
35- platformString = 'darwin' ;
36- break ;
37- case 'linux' :
38- archiveExtension = 'tar.gz' ;
39- platformString = 'linux' ;
40- break ;
41- default :
42- throw new Error ( 'Unsupported platform or architecture' ) ;
27+
28+ const platforms : Record < SupportedPlatforms , { platform : string ; extension : string } > = {
29+ win32 : { platform : 'windows' , extension : 'zip' } ,
30+ darwin : { platform : 'darwin' , extension : 'tar.gz' } ,
31+ linux : { platform : 'linux' , extension : 'tar.gz' }
32+ } ;
33+
34+ const platformKey = this . platform as SupportedPlatforms ;
35+
36+ const platformData = platforms [ platformKey ] ;
37+ if ( ! platformData ) {
38+ throw new Error ( 'Unsupported platform or architecture' ) ;
4339 }
4440
45- return `https://download.checkmarx.com/CxOne/CLI/${ cliVersion } /ast-cli_${ cliVersion } _${ platformString } _x64.${ archiveExtension } ` ;
41+ return `https://download.checkmarx.com/CxOne/CLI/${ cliVersion } /ast-cli_${ cliVersion } _${ platformData . platform } _x64.${ platformData . extension } ` ;
4642 }
4743
4844 getExecutablePath ( ) : string {
@@ -55,7 +51,7 @@ export class CxInstaller {
5551 return executablePath ;
5652 }
5753
58- async downloadIfNotInstalledCLI ( ) {
54+ async downloadIfNotInstalledCLI ( ) : Promise < void > {
5955 const [ _ , release ] = await CxInstaller . installSemaphore . acquire ( ) ;
6056 try {
6157 if ( this . checkExecutableExists ( ) ) {
@@ -70,40 +66,38 @@ export class CxInstaller {
7066 logger . info ( 'Downloaded CLI to:' , zipPath ) ;
7167
7268 await this . extractArchive ( zipPath , this . resourceDirPath ) ;
73- fs1 . chmodSync ( this . getExecutablePath ( ) , 0o777 ) ;
69+ fs . chmodSync ( this . getExecutablePath ( ) , 0o755 ) ;
7470 logger . info ( 'Extracted CLI to:' , this . resourceDirPath ) ;
7571 } catch ( error ) {
7672 logger . error ( 'Error during installation:' , error ) ;
7773 } finally {
78- release ( ) ;
74+ release ( ) ;
7975 }
8076 }
8177
8278 async extractArchive ( zipPath : string , extractPath : string ) : Promise < void > {
8379 if ( zipPath . endsWith ( '.zip' ) ) {
8480 await unzipper . Open . file ( zipPath )
85- . then ( d => d . extract ( { path : extractPath } ) ) ;
81+ . then ( d => d . extract ( { path : extractPath } ) ) ;
8682 } else if ( zipPath . endsWith ( '.tar.gz' ) ) {
87- await tar . extract ( { file : zipPath , cwd : extractPath } ) ;
83+ await tar . extract ( { file : zipPath , cwd : extractPath } ) ;
8884 } else {
8985 logger . error ( 'Unsupported file type. Only .zip and .tar.gz are supported.' ) ;
9086 }
9187 }
9288
9389 async downloadFile ( url : string , outputPath : string ) {
9490 logger . info ( 'Downloading file from:' , url ) ;
95- const writer = fs1 . createWriteStream ( outputPath ) ;
96- const response = await axios ( { url, responseType : 'stream' } ) ;
91+ const writer = fs . createWriteStream ( outputPath ) ;
92+ const response = await axios ( { url, responseType : 'stream' } ) ;
9793 response . data . pipe ( writer ) ;
9894
99- return new Promise ( ( resolve , reject ) => {
100- writer . on ( 'finish' , resolve ) ;
101- writer . on ( 'error' , reject ) ;
102- } ) ;
95+ await finished ( writer ) ; // Use stream promises to await the writer
96+ logger . info ( 'Download finished' ) ;
10397 }
10498
10599 checkExecutableExists ( ) : boolean {
106- return fs1 . existsSync ( this . getExecutablePath ( ) ) ;
100+ return fs . existsSync ( this . getExecutablePath ( ) ) ;
107101 }
108102
109103 async readASTCLIVersion ( ) : Promise < string > {
@@ -112,10 +106,11 @@ export class CxInstaller {
112106 }
113107 try {
114108 const versionFilePath = path . join ( process . cwd ( ) , 'checkmarx-ast-cli.version' ) ;
115- const versionContent = await fs . readFile ( versionFilePath , 'utf-8' ) ;
109+ const versionContent = await fsPromises . readFile ( versionFilePath , 'utf-8' ) ;
116110 return versionContent . trim ( ) ;
117111 } catch ( error ) {
118112 logger . error ( 'Error reading AST CLI version: ' + error . message ) ;
113+ return this . cliDefaultVersion ;
119114 }
120115 }
121116}
0 commit comments