import * as plugins from './mod.plugins.js'; import { PackageManagerUtil, type TPackageManager, type IPackageManagerInfo, type IInstalledPackage } from '../mod_update/classes.packagemanager.js'; import { GITZONE_PACKAGES } from '../mod_update/index.js'; export interface IInstallOptions { yes?: boolean; verbose?: boolean; } export const run = async (options: IInstallOptions = {}): Promise => { const pmUtil = new PackageManagerUtil(); const verbose = options.verbose === true; console.log('Scanning for missing @git.zone packages...\n'); // 1. Detect available package managers const detectedPMs: IPackageManagerInfo[] = []; for (const pm of ['npm', 'yarn', 'pnpm'] as TPackageManager[]) { const info = await pmUtil.detectPackageManager(pm, verbose); if (info.available) { detectedPMs.push(info); } } if (detectedPMs.length === 0) { console.log('No package managers found (npm, yarn, pnpm).'); return; } if (verbose) { console.log(`Detected package managers: ${detectedPMs.map(p => p.name).join(', ')}\n`); } // 2. Collect all globally installed @git.zone packages across all PMs const installedByPm = new Map(); const allInstalledNames = new Set(); for (const pmInfo of detectedPMs) { const installed = await pmUtil.getInstalledPackages(pmInfo.name); installedByPm.set(pmInfo.name, installed); for (const pkg of installed) { if (GITZONE_PACKAGES.includes(pkg.name)) { allInstalledNames.add(pkg.name); } } } // 3. Determine which managed packages are not installed const notInstalled = GITZONE_PACKAGES.filter(name => !allInstalledNames.has(name)); if (notInstalled.length === 0) { console.log('All managed @git.zone packages are already installed.'); return; } console.log(`Found ${notInstalled.length} package(s) not installed.\n`); // 4. Determine the best default PM (the one with most @git.zone packages) let bestPm = detectedPMs[0].name; let bestCount = 0; for (const pmInfo of detectedPMs) { const pkgs = installedByPm.get(pmInfo.name) || []; const gitzoneCount = pkgs.filter(p => GITZONE_PACKAGES.includes(p.name)).length; if (gitzoneCount > bestCount) { bestCount = gitzoneCount; bestPm = pmInfo.name; } } let selectedPm: TPackageManager; let selectedPackages: string[]; if (options.yes === true) { // Non-interactive: use best PM, install all missing selectedPm = bestPm; selectedPackages = notInstalled; console.log(`Using ${selectedPm} (auto-detected).\n`); } else { // 5. Ask which PM to use const smartinteractInstance = new plugins.smartinteract.SmartInteract(); if (detectedPMs.length === 1) { selectedPm = detectedPMs[0].name; console.log(`Using ${selectedPm} (only available PM).\n`); } else { const pmAnswer = await smartinteractInstance.askQuestion({ name: 'packageManager', type: 'list', message: 'Which package manager should be used for installation?', default: bestPm, choices: detectedPMs.map(pm => ({ name: `${pm.name}${pm.name === bestPm ? ' (recommended — most @git.zone packages)' : ''}`, value: pm.name, })), }); selectedPm = pmAnswer.value as TPackageManager; } // 6. Ask which packages to install // Fetch latest versions for display const choicesWithVersions: Array<{ name: string; value: string }> = []; for (const pkgName of notInstalled) { const latest = await pmUtil.getLatestVersion(pkgName); const versionLabel = latest ? `@${latest}` : ''; choicesWithVersions.push({ name: `${pkgName}${versionLabel}`, value: pkgName, }); } const pkgAnswer = await smartinteractInstance.askQuestion({ name: 'packages', type: 'checkbox', message: 'Select packages to install:', default: notInstalled, // all pre-checked choices: choicesWithVersions, }); selectedPackages = pkgAnswer.value as string[]; if (selectedPackages.length === 0) { console.log('No packages selected. Nothing to install.'); return; } } // 7. Install selected packages console.log(`Installing ${selectedPackages.length} package(s) via ${selectedPm}...\n`); let successCount = 0; let failCount = 0; for (const pkgName of selectedPackages) { const success = await pmUtil.executeUpdate(selectedPm, pkgName); if (success) { console.log(` ✓ ${pkgName} installed successfully`); successCount++; } else { console.log(` ✗ ${pkgName} installation failed`); failCount++; } } // 8. Summary console.log(''); if (failCount === 0) { console.log(`All ${successCount} package(s) installed successfully!`); } else { console.log(`Installed ${successCount} package(s), ${failCount} failed.`); } };