UNPKG

camera.ui

Version:
148 lines 5.83 kB
import { sleep } from '@camera.ui/common/utils'; import { pathExists, remove } from 'fs-extra/esm'; import { execSync } from 'node:child_process'; import { createWriteStream } from 'node:fs'; import { arch } from 'node:os'; import { resolve } from 'node:path'; import { Readable } from 'node:stream'; import { finished } from 'node:stream/promises'; import { BasePlatform } from './base.js'; export class Win32Installer extends BasePlatform { async install() { this.checkIsAdmin(); await this.cli.portCheck(); await this.cli.homePathCheck(); try { // download nssm.exe to help create the service const nssmPath = await this.downloadNssm(); // commands to run // eslint-disable-next-line no-useless-escape const installCmd = `"${nssmPath}" install ${this.cli.serviceName} ` + `"${process.execPath}" "\""${this.cli.selfPath}"\"" run -H "\""${this.cli.homePath}"\""`; const setUserDirCmd = `"${nssmPath}" set ${this.cli.serviceName} AppEnvironmentExtra ` + `":CAMERA_UI_HOME_PATH=${this.cli.homePath}` + `:CAMERA_UI_STORAGE_PATH=${this.cli.storagePath}"`; execSync(installCmd); execSync(setUserDirCmd); await this.configureFirewall(); await this.start(); } catch (e) { console.error(e.toString()); this.cli.logger('ERROR: Failed Operation', 'fail'); } } async uninstall() { this.checkIsAdmin(); // stop existing service await this.stop(); try { execSync(`sc delete ${this.cli.serviceName}`); this.cli.logger(`Removed ${this.cli.serviceName} service`, 'succeed'); } catch (e) { console.error(e.toString()); this.cli.logger('ERROR: Failed Operation', 'fail'); } } async reinstall() { this.checkIsAdmin(); await this.uninstall(); await sleep(2000); await this.install(); } async start(restart) { this.checkIsAdmin(); try { execSync(`sc start ${this.cli.serviceName}`); this.cli.logger(`${this.cli.serviceName} ${restart ? 'restarted' : 'started'}`, 'succeed'); await this.waitForApiAndPrintInstructions(restart ? 'restart' : 'start'); } catch (error) { this.cli.logger(`Failed to ${restart ? 'restart' : 'start'} ${this.cli.serviceName}: ${error.message}`, 'fail'); } } async stop() { this.checkIsAdmin(); try { execSync(`sc stop ${this.cli.serviceName}`); this.cli.logger(`${this.cli.serviceName} stopped`, 'succeed'); } catch (error) { this.cli.logger(`Failed to stop ${this.cli.serviceName}: ${error.message}`, 'fail'); } } async restart() { this.checkIsAdmin(); await this.stop(); await sleep(2000); await this.start(true); } async waitForApiAndPrintInstructions(type) { const apiReady = await this.cli.waitForApiHealth(); if (apiReady) { await this.cli.printPostInstallInstructions(type); } else { this.cli.logger('WARNING: There might be errors, or the setup might still be in progress.\n' + ' You can check the logs using the command: cameraui logs', 'warn'); } } checkIsAdmin() { try { execSync('fsutil dirty query %systemdrive% >nul'); } catch { this.cli.logger('ERROR: This command must be run as an Administrator', 'fail'); this.cli.logger('Node.js command prompt shortcut -> Right Click -> Run as administrator', 'fail'); process.exit(1); } } async downloadNssm() { const fileName = `nssm_${arch()}.exe`; const downloadUrl = `https://github.com/homebridge/nssm/releases/download/2.24-101-g897c7ad/${fileName}`; const nssmPath = resolve(this.cli.homePath, 'nssm.exe'); if (await pathExists(nssmPath)) { return nssmPath; } this.cli.logger(`Downloading NSSM from ${downloadUrl}`, 'info'); try { const response = await fetch(downloadUrl); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } if (!response.body) { throw new Error('No response body'); } this.cli.logger(`Writing ${fileName} to ${nssmPath}`, 'info'); const fileStream = createWriteStream(nssmPath, { flags: 'wx' }); await finished(Readable.fromWeb(response.body).pipe(fileStream)); return nssmPath; } catch (error) { // cleanup await remove(nssmPath); this.cli.logger(`Failed to download nssm: ${error.message}`, 'fail'); throw error; } } async configureFirewall() { // firewall commands const cleanFirewallCmd = 'netsh advfirewall firewall Delete rule name="camera.ui"'; const openFirewallCmd = `netsh advfirewall firewall add rule name="camera.ui" dir=in action=allow program="${process.execPath}"`; // try and remove any existing rules so there are not any duplicates try { execSync(cleanFirewallCmd); } catch { // this is probably ok, the firewall rule may not exist to remove } // create a new firewall rule try { execSync(openFirewallCmd); } catch (e) { this.cli.logger('Failed to configure firewall rule for camera.ui.', 'warn'); this.cli.logger(e, 'warn'); } } } //# sourceMappingURL=win32.js.map