/ src / handlers / installer.js
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  }