UNPKG

camera.ui

Version:
176 lines 6.87 kB
import { sleep } from '@camera.ui/common/utils'; import { execSync } from 'node:child_process'; import { existsSync, unlinkSync } from 'node:fs'; import { writeFile } from 'node:fs/promises'; import { userInfo } from 'node:os'; import { resolve } from 'node:path'; import { BasePlatform } from './base.js'; export class DarwinInstaller extends BasePlatform { user; get plistName() { return `com.${this.cli.serviceName.toLowerCase()}.server`; } get plistPath() { return resolve('/Library/LaunchDaemons/', this.plistName + '.plist'); } async install() { this.checkForRoot(); await this.cli.portCheck(); await this.cli.homePathCheck(); try { const la = await this.createLaunchAgent(); console.log('\r\n'); console.log(la); console.log('\r\n'); await this.start(); } catch (e) { console.error(e.toString()); this.cli.logger('ERROR: Failed Operation', 'fail'); } } async uninstall() { this.checkForRoot(); await this.stop(); try { if (existsSync(this.plistPath)) { this.cli.logger(`Removed ${this.cli.serviceName} service`, 'succeed'); unlinkSync(this.plistPath); } else { this.cli.logger(`Could not find installed ${this.cli.serviceName} service.`, 'fail'); } } catch (e) { console.error(e.toString()); this.cli.logger('ERROR: Failed Operation', 'fail'); } } async reinstall() { this.checkForRoot(); await this.uninstall(); await sleep(2000); await this.install(); } async start(restart) { this.checkForRoot(); try { execSync(`launchctl load -w ${this.plistPath}`); 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.checkForRoot(); try { execSync(`launchctl unload -w ${this.plistPath}`); 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.checkForRoot(); await this.stop(); await sleep(2000); await this.start(true); } async getId() { if ((process.getuid?.() === 0 && this.cli.asUser) || process.env.SUDO_USER) { const uid = execSync(`id -u ${this.cli.asUser ?? process.env.SUDO_USER}`).toString('utf8'); const gid = execSync(`id -g ${this.cli.asUser ?? process.env.SUDO_USER}`).toString('utf8'); return { uid: parseInt(uid, 10), gid: parseInt(gid, 10), }; } else { return { uid: userInfo().uid, gid: userInfo().gid, }; } } getPidOfPort(port) { try { return execSync(`lsof -n -iTCP:${port} -sTCP:LISTEN -t 2> /dev/null`).toString('utf8').trim(); } catch { return null; } } 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'); } } checkForRoot() { if (process.getuid?.() !== 0) { this.cli.logger('ERROR: This command must be executed using sudo on macOS', 'fail'); this.cli.logger(`sudo cameraui ${this.cli.action}`, 'fail'); process.exit(1); } if (!process.env.SUDO_USER && !this.cli.asUser) { this.cli.logger('ERROR: Could not detect user. Pass in the user you want to run camera.ui as using the --user flag eg.', 'fail'); this.cli.logger(`sudo cameraui ${this.cli.action} --user your-user`, 'fail'); process.exit(1); } this.user = this.cli.asUser ?? process.env.SUDO_USER; } async createLaunchAgent() { const plistFileContents = [ '<?xml version="1.0" encoding="UTF-8"?>', '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">', '<plist version="1.0">', '<dict>', ' <key>RunAtLoad</key>', ' <true/>', ' <key>KeepAlive</key>', ' <true/>', ' <key>Label</key>', ` <string>${this.plistName}</string>`, ' <key>ProgramArguments</key>', ' <array>', ` <string>${process.execPath}</string>`, ` <string>${this.cli.selfPath}</string>`, ' <string>run</string>', ' <string>-H</string>', ` <string>${this.cli.homePath}</string>`, ' </array>', ' <key>WorkingDirectory</key>', ` <string>${this.cli.homePath}</string>`, ' <key>StandardOutPath</key>', ` <string>${this.cli.storagePath}/camera.ui.log</string>`, ' <key>StandardErrorPath</key>', ` <string>${this.cli.storagePath}/camera.ui.log</string>`, ' <key>UserName</key>', ` <string>${this.user}</string>`, ' <key>EnvironmentVariables</key>', ' <dict>', ' <key>PATH</key>', ` <string>${this.cli.processPath}</string>`, ' <key>HOME</key>', ` <string>${this.cli.getUserHomeDir()}</string>`, ' <key>CAMERA_UI_HOME_PATH</key>', ` <string>${this.cli.homePath}</string>`, ' <key>CAMERA_UI_STORAGE_PATH</key>', ` <string>${this.cli.storagePath}</string>`, ' </dict>', '</dict>', '</plist>', ] .filter((x) => x) .join('\n'); await writeFile(this.plistPath, plistFileContents); return plistFileContents; } } //# sourceMappingURL=darwin.js.map