import { ipcMain, dialog } from "electron"; import { execSync } from "child_process"; import { platform, arch } from "os"; import { NodeSystemInfo } from "../ipc_types"; import fixPath from "fix-path"; import { runShellCommand } from "../utils/runShellCommand"; import log from "electron-log"; import { existsSync } from "fs"; import { join } from "path"; import { readSettings } from "../../main/settings"; const logger = log.scope("node_handlers"); export function registerNodeHandlers() { ipcMain.handle("nodejs-status", async (): Promise => { logger.log( "handling ipc: nodejs-status for platform:", platform(), "and arch:", arch(), ); // Run checks in parallel const [nodeVersion, pnpmVersion] = await Promise.all([ runShellCommand("node --version"), // First, check if pnpm is installed. // If not, try to install it using corepack. // If both fail, then pnpm is not available. runShellCommand( "pnpm --version || (corepack enable pnpm && pnpm --version) || (npm install -g pnpm@latest-10 && pnpm --version)", ), ]); // Default to mac download url. let nodeDownloadUrl = "https://nodejs.org/dist/v22.14.0/node-v22.14.0.pkg"; if (platform() == "win32") { if (arch() === "arm64" || arch() === "arm") { nodeDownloadUrl = "https://nodejs.org/dist/v22.14.0/node-v22.14.0-arm64.msi"; } else { // x64 is the most common architecture for Windows so it's the // default download url. nodeDownloadUrl = "https://nodejs.org/dist/v22.14.0/node-v22.14.0-x64.msi"; } } return { nodeVersion, pnpmVersion, nodeDownloadUrl }; }); ipcMain.handle("reload-env-path", async (): Promise => { logger.debug("Reloading env path, previously:", process.env.PATH); if (platform() === "win32") { const newPath = execSync("cmd /c echo %PATH%", { encoding: "utf8", }).trim(); process.env.PATH = newPath; } else { fixPath(); } const settings = readSettings(); if (settings.customNodePath) { const separator = platform() === "win32" ? ";" : ":"; process.env.PATH = `${settings.customNodePath}${separator}${process.env.PATH}`; logger.debug( "Added custom Node.js path to PATH:", settings.customNodePath, ); } logger.debug("Reloaded env path, now:", process.env.PATH); }); ipcMain.handle("select-node-folder", async () => { const result = await dialog.showOpenDialog({ title: "Select Node.js Installation Folder", properties: ["openDirectory"], message: "Select the folder where Node.js is installed", }); if (result.canceled) { return { path: null, canceled: true, selectedPath: null }; } if (!result.filePaths[0]) { return { path: null, canceled: false, selectedPath: null }; } const selectedPath = result.filePaths[0]; // Verify Node.js exists in selected path const nodeBinary = platform() === "win32" ? "node.exe" : "node"; const nodePath = join(selectedPath, nodeBinary); if (!existsSync(nodePath)) { // Check bin subdirectory (common on Unix systems) const binPath = join(selectedPath, "bin", nodeBinary); if (existsSync(binPath)) { return { path: join(selectedPath, "bin"), canceled: false, selectedPath, }; } return { path: null, canceled: false, selectedPath }; } return { path: selectedPath, canceled: false, selectedPath }; }); }