camera.ui
Version:
camera.ui launcher
148 lines • 5.83 kB
JavaScript
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