Restructure code into separate files

This commit is contained in:
Sander Declerck 2026-01-19 14:46:04 +01:00
parent d03a3a3a4b
commit 27980aec82
No known key found for this signature in database
4 changed files with 193 additions and 169 deletions

View file

@ -0,0 +1,40 @@
import { createWriteStream } from "fs";
import { pipeline } from "stream/promises";
import fetch from "make-fetch-happen";
const ULTIMATE_VERSION = "v0.2.0";
/**
* @typedef {"windows"} Platform
* @typedef {"amd64" | "arm64"} Architecture
*/
/**
* Builds the download URL for the SafeChain Agent installer.
* @param {Platform} platform
* @param {Architecture} architecture
*/
export function getAgentDownloadUrl(platform, architecture) {
const extension = platform === "windows" ? "msi" : "pkg";
return `https://github.com/AikidoSec/safechain-internals/releases/download/${ULTIMATE_VERSION}/SafeChainAgent-${platform}-${architecture}.${extension}`;
}
/**
* Downloads a file from a URL to a local path.
* @param {string} url
* @param {string} destPath
*/
export async function downloadFile(url, destPath) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Download failed: ${response.statusText}`);
}
await pipeline(response.body, createWriteStream(destPath));
}
/**
* Returns the current agent version.
*/
export function getAgentVersion() {
return ULTIMATE_VERSION;
}

View file

@ -0,0 +1,146 @@
import { arch, tmpdir } from "os";
import { unlinkSync } from "fs";
import { join } from "path";
import { execSync } from "child_process";
import { ui } from "../environment/userInteraction.js";
import {
getAgentDownloadUrl,
getAgentVersion,
downloadFile,
} from "./downloadAgent.js";
export async function installOnWindows() {
if (!isRunningAsAdmin()) {
ui.writeError("Administrator privileges required.");
ui.writeInformation(
"Please run this command in an elevated terminal (Run as Administrator).",
);
return;
}
const architecture = getWindowsArchitecture();
const downloadUrl = getAgentDownloadUrl("windows", architecture);
const msiPath = join(tmpdir(), `SafeChainAgent-${Date.now()}.msi`);
ui.emptyLine();
ui.writeInformation(
`📥 Downloading SafeChain Agent ${getAgentVersion()} (${architecture})...`,
);
ui.writeVerbose(`Download URL: ${downloadUrl}`);
ui.writeVerbose(`Destination: ${msiPath}`);
await downloadFile(downloadUrl, msiPath);
ui.emptyLine();
stopServiceIfRunning();
uninstallIfInstalled();
// Wait a moment for uninstall to complete
await new Promise((resolve) => setTimeout(resolve, 2000));
ui.writeInformation("⚙️ Installing SafeChain Agent...");
runMsiInstaller(msiPath);
ui.emptyLine();
ui.writeInformation("🚀 Starting SafeChain Agent service...");
startService();
ui.writeVerbose(`Cleaning up temporary file: ${msiPath}`);
cleanup(msiPath);
ui.emptyLine();
ui.writeInformation("✅ SafeChain Agent installed and started successfully!");
ui.emptyLine();
}
function isRunningAsAdmin() {
try {
execSync("net session", { stdio: "ignore" });
return true;
} catch {
return false;
}
}
function getWindowsArchitecture() {
const nodeArch = arch();
if (nodeArch === "x64") return "amd64";
if (nodeArch === "arm64") return "arm64";
throw new Error(`Unsupported architecture: ${nodeArch}`);
}
function uninstallIfInstalled() {
try {
// Use PowerShell to find the product code, then use msiexec to uninstall
// This is the modern alternative to wmic which is deprecated
const findProductCodeCmd = `powershell -Command "$app = Get-WmiObject -Class Win32_Product -Filter \\"Name='SafeChain Agent'\\"; if ($app) { Write-Output $app.IdentifyingNumber }"`;
ui.writeVerbose(`Finding product code: ${findProductCodeCmd}`);
const productCode = execSync(findProductCodeCmd, {
encoding: "utf8",
}).trim();
if (productCode) {
ui.writeInformation("🗑️ Removing previous installation...");
ui.writeVerbose(`Found product code: ${productCode}`);
ui.writeVerbose(`Running: msiexec /x ${productCode} /qn /norestart`);
execSync(`msiexec /x ${productCode} /qn /norestart`, {
stdio: "inherit",
});
} else {
ui.writeVerbose("No existing installation found (fresh install).");
}
} catch {
// Not installed or uninstall failed, which is fine for a fresh install
ui.writeVerbose("No existing installation found (fresh install).");
}
}
/**
* @param {string} msiPath
*/
function runMsiInstaller(msiPath) {
// /i = install
// /qn = quiet mode (no UI)
ui.writeVerbose(`Running: msiexec /i "${msiPath}" /qn`);
execSync(`msiexec /i "${msiPath}" /qn`, { stdio: "inherit" });
}
function stopServiceIfRunning() {
try {
ui.writeInformation("⏹️ Stopping running service...");
ui.writeVerbose('Running: net stop "SafeChainAgent"');
execSync('net stop "SafeChainAgent"', { stdio: "inherit" });
} catch {
// Service is not running or doesn't exist, which is fine
ui.writeVerbose("Service not running (will start after installation).");
}
}
function startService() {
try {
// Check if service is already running
ui.writeVerbose('Checking service status: sc query "SafeChainAgent"');
const status = execSync('sc query "SafeChainAgent"', { encoding: "utf8" });
if (status.includes("RUNNING")) {
ui.writeVerbose("SafeChain Agent service is already running.");
return;
}
} catch {
// Service might not exist yet or query failed, proceed with start
}
ui.writeVerbose('Running: net start "SafeChainAgent"');
execSync('net start "SafeChainAgent"', { stdio: "inherit" });
}
/**
* @param {string} msiPath
*/
function cleanup(msiPath) {
try {
unlinkSync(msiPath);
} catch {
// Ignore cleanup errors
}
}

View file

@ -1,13 +1,7 @@
import { platform, arch, tmpdir } from "os";
import { createWriteStream, unlinkSync } from "fs";
import { join } from "path";
import { execSync } from "child_process";
import { pipeline } from "stream/promises";
import fetch from "make-fetch-happen";
import { platform } from "os";
import { ui } from "../environment/userInteraction.js";
import { initializeCliArguments } from "../config/cliArguments.js";
const ULTIMATE_VERSION = "v0.2.0";
import { installOnWindows } from "./installOnWindows.js";
export function installUltimate() {
initializeCliArguments(process.argv);
@ -22,159 +16,3 @@ export function installUltimate() {
);
}
}
async function installOnWindows() {
if (!isRunningAsAdmin()) {
ui.writeError("Administrator privileges required.");
ui.writeInformation(
"Please run this command in an elevated terminal (Run as Administrator).",
);
return;
}
const architecture = getWindowsArchitecture();
const downloadUrl = buildDownloadUrl(architecture);
const msiPath = join(tmpdir(), `SafeChainAgent-${Date.now()}.msi`);
ui.emptyLine();
ui.writeInformation(
`📥 Downloading SafeChain Agent ${ULTIMATE_VERSION} (${architecture})...`,
);
ui.writeVerbose(`Download URL: ${downloadUrl}`);
ui.writeVerbose(`Destination: ${msiPath}`);
await downloadFile(downloadUrl, msiPath);
ui.emptyLine();
stopServiceIfRunning();
uninstallIfInstalled();
// Wait a moment for uninstall to complete
await new Promise((resolve) => setTimeout(resolve, 2000));
ui.writeInformation("⚙️ Installing SafeChain Agent...");
ui.writeVerbose(`Running: msiexec /i "${msiPath}" /qn /norestart`);
runMsiInstaller(msiPath);
ui.emptyLine();
ui.writeInformation("🚀 Starting SafeChain Agent service...");
startService();
ui.writeVerbose(`Cleaning up temporary file: ${msiPath}`);
cleanup(msiPath);
ui.emptyLine();
ui.writeInformation("✅ SafeChain Agent installed and started successfully!");
ui.emptyLine();
}
function isRunningAsAdmin() {
try {
execSync("net session", { stdio: "ignore" });
return true;
} catch {
return false;
}
}
function getWindowsArchitecture() {
const nodeArch = arch();
if (nodeArch === "x64") return "amd64";
if (nodeArch === "arm64") return "arm64";
throw new Error(`Unsupported architecture: ${nodeArch}`);
}
/**
* @param {string} architecture
*/
function buildDownloadUrl(architecture) {
return `https://github.com/AikidoSec/safechain-internals/releases/download/${ULTIMATE_VERSION}/SafeChainAgent-windows-${architecture}.msi`;
}
/**
* @param {string} url
* @param {string} destPath
*/
async function downloadFile(url, destPath) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Download failed: ${response.statusText}`);
}
await pipeline(response.body, createWriteStream(destPath));
}
function uninstallIfInstalled() {
try {
// Use PowerShell to find the product code, then use msiexec to uninstall
// This is the modern alternative to wmic which is deprecated
const findProductCodeCmd = `powershell -Command "$app = Get-WmiObject -Class Win32_Product -Filter \\"Name='SafeChain Agent'\\"; if ($app) { Write-Output $app.IdentifyingNumber }"`;
ui.writeVerbose(`Finding product code: ${findProductCodeCmd}`);
const productCode = execSync(findProductCodeCmd, {
encoding: "utf8",
}).trim();
if (productCode) {
ui.writeInformation("🗑️ Removing previous installation...");
ui.writeVerbose(`Found product code: ${productCode}`);
ui.writeVerbose(`Running: msiexec /x ${productCode} /qn /norestart`);
execSync(`msiexec /x ${productCode} /qn /norestart`, {
stdio: "inherit",
});
} else {
ui.writeVerbose("No existing installation found (fresh install).");
}
} catch {
// Not installed or uninstall failed, which is fine for a fresh install
ui.writeVerbose("No existing installation found (fresh install).");
}
}
/**
* @param {string} msiPath
*/
function runMsiInstaller(msiPath) {
// /i = install
// /qn = quiet mode (no UI)
// /norestart = suppress restarts
execSync(`msiexec /i "${msiPath}" /qn /norestart`, { stdio: "inherit" });
}
function stopServiceIfRunning() {
try {
ui.writeInformation("⏹️ Stopping running service...");
ui.writeVerbose('Running: net stop "SafeChainAgent"');
execSync('net stop "SafeChainAgent"', { stdio: "inherit" });
} catch {
// Service is not running or doesn't exist, which is fine
ui.writeVerbose("Service not running (will start after installation).");
}
}
function startService() {
try {
// Check if service is already running
ui.writeVerbose('Checking service status: sc query "SafeChainAgent"');
const status = execSync('sc query "SafeChainAgent"', { encoding: "utf8" });
if (status.includes("RUNNING")) {
ui.writeVerbose("SafeChain Agent service is already running.");
return;
}
} catch {
// Service might not exist yet or query failed, proceed with start
}
ui.writeVerbose('Running: net start "SafeChainAgent"');
execSync('net start "SafeChainAgent"', { stdio: "inherit" });
}
/**
* @param {string} msiPath
*/
function cleanup(msiPath) {
try {
unlinkSync(msiPath);
} catch {
// Ignore cleanup errors
}
}

View file

@ -73,20 +73,20 @@ export async function main(args) {
ui.writeVerbose(
`${chalk.green("✔")} Safe-chain: Scanned ${
auditStats.totalPackages
} packages, no malware found.`
} packages, no malware found.`,
);
}
if (proxy.hasSuppressedVersions()) {
ui.writeInformation(
`${chalk.yellow(
""
)} Safe-chain: Some package versions were suppressed due to minimum age requirement.`
"",
)} Safe-chain: Some package versions were suppressed due to minimum age requirement.`,
);
ui.writeInformation(
` To disable this check, use: ${chalk.cyan(
"--safe-chain-skip-minimum-package-age"
)}`
"--safe-chain-skip-minimum-package-age",
)}`,
);
}