UNPKG

penguins-eggs

Version:

A remaster system tool, compatible with Almalinux, Alpine, Arch, Debian, Devuan, Fedora, Manjaro, Opensuse, Ubuntu and derivatives

203 lines (202 loc) 8.37 kB
/** * ./src/classes/daddy.ts * penguins-eggs v.25.7.x / ECMAScript 2020 * author: Piero Proietti (modified by Hossein Seilani) * license: MIT */ import chalk from 'chalk'; import yaml from 'js-yaml'; import fs from 'node:fs/promises'; import path from 'node:path'; import Pacman from '../classes/pacman.js'; import Settings from '../classes/settings.js'; import Utils from '../classes/utils.js'; const __dirname = path.dirname(new URL(import.meta.url).pathname); export default class Daddy { settings = {}; /** * [CHANGE 1] Modular, type-safe, interactive configuration editor * This method asks the user for LiveCD parameters using inquirer and returns * a fully typed IEggsConfig object. It replaces the older JSON.stringify/parse approach. */ async editConfig(config) { console.log(chalk.cyan('Edit and save Live system parameters\n')); const { input, select } = await import('@inquirer/prompts'); // Determine default compression option let compressionOpt = 0; switch (config.compression) { case 'xz': { compressionOpt = 1; break; } case 'xz -Xbcj x86': { compressionOpt = 2; break; } default: { compressionOpt = 0; break; } } // Provide a default snapshot prefix if empty if (!config.snapshot_prefix) { config.snapshot_prefix = Utils.snapshotPrefix(this.settings.distro.distroId, this.settings.distro.codenameId); } try { const snapshot_prefix = await input({ default: config.snapshot_prefix, message: 'LiveCD iso prefix: ', }); const snapshot_basename = await input({ default: config.snapshot_basename, message: 'LiveCD iso basename: ', }); const user_opt = await input({ default: config.user_opt, message: 'LiveCD user:', }); const user_opt_passwd = await input({ default: config.user_opt_passwd, message: 'LiveCD user password:', }); const root_passwd = await input({ default: config.root_passwd, message: 'LiveCD root password:', }); const compression = await select({ choices: [ { name: 'fast', value: 'fast' }, { name: 'max', value: 'max' } ], default: compressionOpt === 0 ? 'fast' : (compressionOpt === 1 ? 'fast' : 'max'), // improving default logic slightly, though simple mapping is fine message: 'LiveCD compression: ', }); const answers = { snapshot_prefix, snapshot_basename, user_opt, user_opt_passwd, root_passwd, compression }; return { ...config, ...answers }; } catch (error) { console.error(chalk.red('Error editing configuration:'), error); throw error; } } /** * [CHANGE 2] Central method to manage environment, configuration and save * This method is modular, type-safe, and handles: * - Pacman and distro templates check * - Load, reset, or apply custom configuration * - Save configuration to disk * - Provide clear guidance to the user */ async helpMe(reset = false, isCustom = false, fileCustom = '', verbose = false) { try { if (isCustom) console.log('Using custom file:', fileCustom); // Step 1: Check system prerequisites await this.checkPacman(verbose); // Step 2: Load settings this.settings = new Settings(); const loaded = await this.settings.load(); let config = loaded ? this.settings.config : {}; // Step 3: Apply reset or custom configuration if (reset || isCustom) { await this.applyResetOrCustomConfig(config, isCustom, fileCustom); } else { config = await this.editConfig(config); } // Step 4: Save final configuration await this.settings.save(config); // Step 5: Display help messages this.displayFinalHelp(); } catch (error) { console.error(chalk.red('An error occurred in helpMe:'), error); } } /** * Load and apply a custom YAML configuration * [CHANGE 3] Async reading of file and type-safe parsing */ async applyCustomYAML(config, fileCustom) { try { const conf = await fs.readFile(fileCustom, 'utf8'); const confCustom = yaml.load(conf); // Safely copy fields from YAML to config config.snapshot_basename = confCustom.snapshot_basename ?? config.snapshot_basename; config.snapshot_prefix = confCustom.snapshot_prefix ?? config.snapshot_prefix; config.user_opt = confCustom.user_opt ?? config.user_opt; config.user_opt_passwd = confCustom.user_opt_passwd ?? config.user_opt_passwd; config.root_passwd = confCustom.root_passwd ?? config.root_passwd; config.theme = confCustom.theme ?? config.theme; } catch (error) { console.error(chalk.red('Failed to load custom YAML config:'), error); throw error; } } /** * Apply reset or custom configuration */ async applyResetOrCustomConfig(config, isCustom, fileCustom) { if (!config.snapshot_prefix) { /** * add fstype: btrfs, xfs, etc */ // let fstype = ''; // try { // const { data } = await exec(`findmnt -n -o FSTYPE /`, { capture: true }); // fstype = data.trim() === 'ext4' ? '' : `${data.trim()}-`; // } catch (err) { // console.warn('Unable to detect FSTYPE:', err); // } config.snapshot_prefix = Utils.snapshotPrefix(this.settings.distro.distroId, this.settings.distro.codenameId); } // Apply custom YAML if needed if (isCustom && fileCustom) { await this.applyCustomYAML(config, fileCustom); } } /** * Check and install Pacman configuration and templates if missing */ async checkPacman(verbose) { if (!Pacman.configurationCheck()) { console.log('- creating configuration directory...'); await Pacman.configurationInstall(verbose); } if (!Pacman.distroTemplateCheck()) { console.log('- installing distro template...'); await Pacman.distroTemplateInstall(verbose); } if (!Pacman.calamaresExists() && Pacman.isInstalledGui() && Pacman.isCalamaresAvailable()) { console.log('- GUI system detected, calamares is available but not installed.'); } } /** * Display final guidance and tips to the user * [CHANGE 4] Modular, clear, user-friendly messages */ displayFinalHelp() { console.log(); console.log(chalk.cyan('Your configuration was saved on: /etc/penguins-eggs.d')); console.log(chalk.cyan('You can create a clean ISO with: ') + chalk.white('sudo eggs produce')); console.log(chalk.cyan('Or a full personal clone: ') + chalk.white('sudo eggs produce --clone')); console.log(); console.log(chalk.cyan('If you don’t have enough space to remaster, you can mount remote or local space:')); console.log(chalk.cyan('- Create a hidden mountpoint under the nest:')); console.log(chalk.white('sudo mkdir /home/eggs/mnt -p')); console.log(chalk.cyan('- Mount remote space:')); console.log(chalk.white('sudo sshfs -o allow_other root@192.168.1.2:/zfs/iso /home/eggs/mnt')); console.log(chalk.cyan('- Or mount a local partition:')); console.log(chalk.white('sudo mount /dev/sdx1 /home/eggs/mnt')); console.log(); console.log(chalk.cyan('More help? ') + chalk.white('eggs mom')); } }