import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const DEFAULT_CONFIG_DIRNAME = '.alga-psa-appliance'; function exists(filePath) { try { fs.accessSync(filePath, fs.constants.R_OK); return true; } catch { return false; } } function isDirectory(filePath) { try { return fs.statSync(filePath).isDirectory(); } catch { return false; } } function walkUpForRepo(startDir) { let cursor = path.resolve(startDir); while (true) { const candidate = path.join(cursor, 'ee', 'appliance', 'scripts', 'collect-support-bundle.sh'); if (exists(candidate)) { return cursor; } const parent = path.dirname(cursor); if (parent === cursor) { return null; } cursor = parent; } } export function resolveRuntimePaths(options = {}) { const assetRoot = options.assetRoot || process.env.ALGA_APPLIANCE_ASSET_ROOT || null; if (assetRoot) { return { runtimeMode: 'asset-root', assetRoot: path.resolve(assetRoot), scriptsDir: path.resolve(assetRoot, 'scripts'), fluxDir: path.resolve(assetRoot, 'flux'), supportBundleScript: path.resolve(assetRoot, 'scripts', 'collect-support-bundle.sh'), repairScript: path.resolve(assetRoot, 'scripts', 'repair-release.sh'), resetScript: path.resolve(assetRoot, 'scripts', 'reset-appliance-data.sh'), }; } const base = walkUpForRepo(options.cwd || process.cwd()) || walkUpForRepo(path.dirname(fileURLToPath(import.meta.url))); if (!base) { throw new Error('Unable to resolve appliance runtime paths. Set ALGA_APPLIANCE_ASSET_ROOT.'); } return { runtimeMode: 'repo', repoRoot: base, assetRoot: path.join(base, 'ee', 'appliance'), scriptsDir: path.join(base, 'ee', 'appliance', 'scripts'), fluxDir: path.join(base, 'ee', 'appliance', 'flux'), supportBundleScript: path.join(base, 'ee', 'appliance', 'scripts', 'collect-support-bundle.sh'), repairScript: path.join(base, 'ee', 'appliance', 'scripts', 'repair-release.sh'), resetScript: path.join(base, 'ee', 'appliance', 'scripts', 'reset-appliance-data.sh'), }; } export function resolveConfigBase(homeDir) { const explicitRoot = process.env.ALGA_APPLIANCE_HOME; if (explicitRoot) { return path.resolve(explicitRoot); } return path.join(homeDir, DEFAULT_CONFIG_DIRNAME); } export function listSiteIds(configBaseDir) { if (!isDirectory(configBaseDir)) { return []; } return fs .readdirSync(configBaseDir, { withFileTypes: true }) .filter((entry) => entry.isDirectory()) .map((entry) => entry.name) .sort(); } export function resolveSitePaths(configBaseDir, siteId) { const dir = path.join(configBaseDir, siteId); return { siteId, configDir: dir, kubeconfig: path.join(dir, 'kubeconfig'), talosconfig: path.join(dir, 'talosconfig'), nodeIpFile: path.join(dir, 'node-ip'), appUrlFile: path.join(dir, 'app-url'), }; } export function fileExists(filePath) { return exists(filePath); }