| |
| |
| |
| |
| |
| |
| |
| |
| const { spawnSync } = require("child_process"); |
| const fs = require("fs"); |
| const path = require("path"); |
| const { getRuntimeDir, getRuntimeNodeModules, runNpmInstall, summarizeNpmError } = require("./sqliteRuntime"); |
|
|
| const SYSTRAY_PKG = "systray2"; |
| const SYSTRAY_VERSION = "2.1.4"; |
| const LEGACY_SYSTRAY_PKG = "systray"; |
|
|
| function hasSystray() { |
| return fs.existsSync(path.join(getRuntimeNodeModules(), SYSTRAY_PKG, "package.json")); |
| } |
|
|
| |
| |
| |
| function cleanupLegacySystray({ silent = false } = {}) { |
| |
| |
| |
| const targets = [ |
| path.join(getRuntimeNodeModules(), LEGACY_SYSTRAY_PKG), |
| path.join(__dirname, "..", "node_modules", LEGACY_SYSTRAY_PKG) |
| ]; |
| for (const dir of targets) { |
| if (fs.existsSync(dir)) { |
| try { |
| fs.rmSync(dir, { recursive: true, force: true }); |
| if (!silent) console.log(`[9router][runtime] removed legacy systray: ${dir}`); |
| } catch (e) { |
| if (!silent) console.warn(`[9router][runtime] failed to remove ${dir}: ${e.message}`); |
| } |
| } |
| } |
| } |
|
|
| |
| |
| |
| function chmodSystrayBin({ silent = false } = {}) { |
| if (process.platform === "win32") return; |
| const binName = process.platform === "darwin" ? "tray_darwin_release" : "tray_linux_release"; |
| const binPath = path.join(getRuntimeNodeModules(), SYSTRAY_PKG, "traybin", binName); |
| if (!fs.existsSync(binPath)) return; |
| try { |
| fs.chmodSync(binPath, 0o755); |
| } catch (e) { |
| if (!silent) console.warn(`[9router][runtime] chmod tray bin failed: ${e.message}`); |
| } |
| } |
|
|
| function ensureRuntimeDir() { |
| const dir = getRuntimeDir(); |
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); |
| const pkgPath = path.join(dir, "package.json"); |
| if (!fs.existsSync(pkgPath)) { |
| fs.writeFileSync(pkgPath, JSON.stringify({ |
| name: "9router-runtime", |
| version: "1.0.0", |
| private: true |
| }, null, 2)); |
| } |
| return dir; |
| } |
|
|
| function npmInstall(pkgs, { silent = false } = {}) { |
| const cwd = ensureRuntimeDir(); |
| if (!silent) console.log("β³ Installing system tray (first run)..."); |
| const res = runNpmInstall({ cwd, pkgs, extraArgs: ["--no-save"], timeout: 120000 }); |
| if (!res.ok && !silent) { |
| const reason = summarizeNpmError(res.stderr); |
| console.warn("β οΈ System tray install failed β tray disabled"); |
| console.warn(` Reason: ${reason}`); |
| console.warn(` Retry: cd "${cwd}" && npm install ${pkgs.join(" ")}`); |
| } |
| return res.ok; |
| } |
|
|
| |
| |
| function ensureTrayRuntime({ silent = false } = {}) { |
| |
| |
| cleanupLegacySystray({ silent }); |
|
|
| if (process.platform === "win32") { |
| return { systray: false, skipped: true }; |
| } |
| if (hasSystray()) { |
| chmodSystrayBin({ silent }); |
| if (!silent) console.log("β
System tray ready"); |
| return { systray: true }; |
| } |
| const ok = npmInstall([`${SYSTRAY_PKG}@${SYSTRAY_VERSION}`], { silent }); |
| if (ok) chmodSystrayBin({ silent }); |
| return { systray: ok && hasSystray() }; |
| } |
|
|
| module.exports = { ensureTrayRuntime }; |
|
|