// Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 import * as electron from "electron"; import * as child_process from "node:child_process"; import * as readline from "readline"; import { WebServerEndpointVarName, WSServerEndpointVarName } from "../frontend/util/endpoints"; import { AuthKey, WaveAuthKeyEnv } from "./authkey"; import { setForceQuit } from "./emain-activity"; import { WaveAppPathVarName } from "./emain-util"; import { getElectronAppUnpackedBasePath, getWaveConfigDir, getWaveDataDir, getWaveSrvCwd, getWaveSrvPath, WaveConfigHomeVarName, WaveDataHomeVarName, } from "./platform"; import { updater } from "./updater"; let isWaveSrvDead = false; let waveSrvProc: child_process.ChildProcessWithoutNullStreams | null = null; let WaveVersion = "unknown"; // set by WAVESRV-ESTART let WaveBuildTime = 0; // set by WAVESRV-ESTART export function getWaveVersion(): { version: string; buildTime: number } { return { version: WaveVersion, buildTime: WaveBuildTime }; } let waveSrvReadyResolve = (value: boolean) => {}; const waveSrvReady: Promise = new Promise((resolve, _) => { waveSrvReadyResolve = resolve; }); export function getWaveSrvReady(): Promise { return waveSrvReady; } export function getWaveSrvProc(): child_process.ChildProcessWithoutNullStreams | null { return waveSrvProc; } export function getIsWaveSrvDead(): boolean { return isWaveSrvDead; } export function runWaveSrv(handleWSEvent: (evtMsg: WSEventType) => void): Promise { let pResolve: (value: boolean) => void; let pReject: (reason?: any) => void; const rtnPromise = new Promise((argResolve, argReject) => { pResolve = argResolve; pReject = argReject; }); const envCopy = { ...process.env }; envCopy[WaveAppPathVarName] = getElectronAppUnpackedBasePath(); envCopy[WaveAuthKeyEnv] = AuthKey; envCopy[WaveDataHomeVarName] = getWaveDataDir(); envCopy[WaveConfigHomeVarName] = getWaveConfigDir(); const waveSrvCmd = getWaveSrvPath(); console.log("trying to run local server", waveSrvCmd); const proc = child_process.spawn(getWaveSrvPath(), { cwd: getWaveSrvCwd(), env: envCopy, }); proc.on("exit", (e) => { if (updater?.status == "installing") { return; } console.log("wavesrv exited, shutting down"); setForceQuit(true); isWaveSrvDead = true; electron.app.quit(); }); proc.on("spawn", (e) => { console.log("spawned wavesrv"); waveSrvProc = proc; pResolve(true); }); proc.on("error", (e) => { console.log("error running wavesrv", e); pReject(e); }); const rlStdout = readline.createInterface({ input: proc.stdout, terminal: false, }); rlStdout.on("line", (line) => { console.log(line); }); const rlStderr = readline.createInterface({ input: proc.stderr, terminal: false, }); rlStderr.on("line", (line) => { if (line.includes("WAVESRV-ESTART")) { const startParams = /ws:([a-z0-9.:]+) web:([a-z0-9.:]+) version:([a-z0-9.\-]+) buildtime:(\d+)/gm.exec( line ); if (startParams == null) { console.log("error parsing WAVESRV-ESTART line", line); electron.app.quit(); return; } process.env[WSServerEndpointVarName] = startParams[1]; process.env[WebServerEndpointVarName] = startParams[2]; WaveVersion = startParams[3]; WaveBuildTime = parseInt(startParams[4]); waveSrvReadyResolve(true); return; } if (line.startsWith("WAVESRV-EVENT:")) { const evtJson = line.slice("WAVESRV-EVENT:".length); try { const evtMsg: WSEventType = JSON.parse(evtJson); handleWSEvent(evtMsg); } catch (e) { console.log("error handling WAVESRV-EVENT", e); } return; } console.log(line); }); return rtnPromise; }