installer.js
1 export class Installer { 2 constructor( 3 configService, 4 shellService, 5 osService, 6 fsService, 7 marketplaceSetup, 8 ) { 9 this.config = configService.get(); 10 this.configService = configService; 11 this.shell = shellService; 12 this.os = osService; 13 this.fs = fsService; 14 this.market = marketplaceSetup; 15 } 16 17 isCodexInstalled = async () => { 18 try { 19 await this.getCodexVersion(); 20 return true; 21 } catch (error) { 22 return false; 23 } 24 }; 25 26 getCodexVersion = async () => { 27 const codexExe = this.configService.getCodexExe(); 28 if (!this.fs.isFile(codexExe)) throw new Error("Codex not installed."); 29 const version = await this.shell.run(`"${codexExe}" --version`); 30 if (version.length < 1) throw new Error("Version info not found."); 31 return version; 32 }; 33 34 installCodex = async (processCallbacks) => { 35 this.fs.ensureDirExists(this.config.codexRoot); 36 if (!(await this.arePrerequisitesCorrect(processCallbacks))) return; 37 38 if (!(await this.market.runClientWizard())) return; 39 40 processCallbacks.installStarts(); 41 if (this.os.isWindows()) { 42 await this.installCodexWindows(processCallbacks); 43 } else { 44 await this.installCodexUnix(processCallbacks); 45 } 46 47 if (!(await this.isCodexInstalled())) { 48 processCallbacks.warn("Codex failed to install."); 49 throw new Error("Codex installation failed."); 50 } 51 processCallbacks.installSuccessful(); 52 }; 53 54 uninstallCodex = () => { 55 this.fs.deleteDir(this.config.codexRoot); 56 }; 57 58 arePrerequisitesCorrect = async (processCallbacks) => { 59 if (await this.isCodexInstalled()) { 60 processCallbacks.warn("Codex is already installed."); 61 return false; 62 } 63 if (!this.fs.isDir(this.config.codexRoot)) { 64 processCallbacks.warn("Root path doesn't exist."); 65 return false; 66 } 67 if (!(await this.isCurlAvailable())) { 68 processCallbacks.warn("Curl is not available."); 69 return false; 70 } 71 return true; 72 }; 73 74 isCurlAvailable = async () => { 75 const curlVersion = await this.shell.run("curl --version"); 76 return curlVersion.length > 0; 77 }; 78 79 installCodexWindows = async (processCallbacks) => { 80 await this.shell.run( 81 "curl -LO --ssl-no-revoke https://get.codex.storage/install.cmd", 82 ); 83 processCallbacks.downloadSuccessful(); 84 await this.shell.run( 85 `set "INSTALL_DIR=${this.config.codexRoot}" && ` + 86 `"${this.os.getWorkingDir()}\\install.cmd"`, 87 ); 88 await this.shell.run("del /f install.cmd"); 89 }; 90 91 installCodexUnix = async (processCallbacks) => { 92 if (!(await this.ensureUnixDependencies(processCallbacks))) return; 93 await this.shell.run( 94 "curl -# --connect-timeout 10 --max-time 60 -L https://get.codex.storage/install.sh -o install.sh && chmod +x install.sh", 95 ); 96 processCallbacks.downloadSuccessful(); 97 98 if (this.os.isDarwin()) { 99 await this.runInstallerDarwin(); 100 } else { 101 await this.runInstallerLinux(); 102 } 103 await this.shell.run("rm -f install.sh"); 104 }; 105 106 runInstallerDarwin = async () => { 107 const timeoutCommand = `perl -e ' 108 eval { 109 local $SIG{ALRM} = sub { die "timeout\\n" }; 110 alarm(120); 111 system("INSTALL_DIR=\\"${this.config.codexRoot}\\" bash install.sh"); 112 alarm(0); 113 }; 114 die if $@; 115 '`; 116 await this.shell.run(timeoutCommand); 117 }; 118 119 runInstallerLinux = async () => { 120 await this.shell.run( 121 `INSTALL_DIR="${this.config.codexRoot}" timeout 120 bash install.sh`, 122 ); 123 }; 124 125 ensureUnixDependencies = async (processCallbacks) => { 126 const libgompCheck = await this.shell.run("ldconfig -p | grep libgomp"); 127 if (libgompCheck.length < 1) { 128 processCallbacks.warn("libgomp not found."); 129 return false; 130 } 131 return true; 132 }; 133 }