UNPKG

@interopio/desktop-cli

Version:

io.Connect Desktop Seed Repository CLI Tools

303 lines 15.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ComponentManager = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const utils_1 = require("../utils"); const license_validator_1 = require("./license-validator"); const component_downloader_1 = require("./component-downloader"); const component_storage_1 = require("./component-storage"); const component_registry_1 = require("../components/component-registry"); class ComponentManager { constructor(storageType) { this.licenseValidator = new license_validator_1.LicenseValidator(); this.downloader = component_downloader_1.ComponentDownloader.fromEnvironment(); this.storage = component_storage_1.ComponentStorageFactory.create(storageType); this.componentRegistry = new component_registry_1.ComponentRegistryImpl(); } /** * Get the component registry for external registration of components */ getComponentRegistry() { return this.componentRegistry; } /** * Register a new component processor */ registerComponent(componentName, version) { this.componentRegistry.register(componentName, version); } /** * Check if a component is registered */ isComponentRegistered(componentName) { return this.componentRegistry.has(componentName); } async installAll(platform, arch) { utils_1.Logger.debug(`Installing all components for platform: ${platform}, arch: ${arch}`, 'component'); const components = await utils_1.ConfigManager.getComponentConfig(); utils_1.Logger.debug(`Components to install: ${JSON.stringify(components)}`, 'component'); for (const [name, version] of Object.entries(components)) { await this.install(name, version, platform, arch); this.registerComponent(name, version); } } async install(componentName, version, platform, arch) { try { const targetPlatform = platform || process.platform; const targetArch = arch || process.arch; utils_1.Logger.debug(`Installing component: ${componentName}@${version} for ${targetPlatform}-${targetArch}`, 'component'); utils_1.Logger.info(`Installing component: ${componentName}@${version} for ${targetPlatform}-${targetArch}`); // Validate license allows this component const hasAccess = await this.licenseValidator.validateComponentAccess(componentName); if (!hasAccess) { throw new Error(`License does not allow component: ${componentName}`); } // Get component metadata const metadata = await this.storage.getComponentMetadata(componentName, version); // Check if platform is supported if (!metadata.platforms.includes(targetPlatform)) { throw new Error(`Component ${componentName} is not available for platform: ${targetPlatform}`); } // Check if component exists for this platform/arch const exists = await this.storage.componentExists(componentName, metadata.version, targetPlatform, targetArch); if (!exists) { throw new Error(`Component ${componentName}@${metadata.version} is not available for ${targetPlatform}-${targetArch}`); } // Download and extract component const componentDir = utils_1.PathUtils.getComponentDir(componentName); await utils_1.FileUtils.ensureDir(componentDir); await this.downloadAndExtractComponent(metadata, componentDir, targetPlatform, targetArch); utils_1.Logger.success(`Component ${componentName}@${version} installed successfully for ${targetPlatform}-${targetArch}`); } catch (error) { utils_1.Logger.error(`Failed to install ${componentName}@${version}: ${error instanceof Error ? error.message : String(error)}`); throw error; } } async remove(componentName) { try { utils_1.Logger.info(`Removing component: ${componentName}`); const componentDir = utils_1.PathUtils.getComponentDir(componentName); if (await utils_1.FileUtils.exists(componentDir)) { await utils_1.FileUtils.removeFile(componentDir); } // Update package.json const components = await utils_1.ConfigManager.getComponentConfig(); delete components[componentName]; await utils_1.ConfigManager.updateComponentConfig(components); utils_1.Logger.success(`Component ${componentName} removed successfully`); } catch (error) { utils_1.Logger.error(`Failed to remove ${componentName}: ${error instanceof Error ? error.message : String(error)}`); throw error; } } async add(componentName, version, platform, arch) { await this.install(componentName, version, platform, arch); // Update package.json const components = await utils_1.ConfigManager.getComponentConfig(); components[componentName] = version; await utils_1.ConfigManager.updateComponentConfig(components); } async update(componentName, platform, arch) { if (componentName) { // Update specific component const components = await utils_1.ConfigManager.getComponentConfig(); if (!components[componentName]) { throw new Error(`Component ${componentName} is not installed`); } const currentVersion = components[componentName]; // Check for the latest available version utils_1.Logger.info(`Checking for updates for ${componentName}@${currentVersion}...`); try { const latestVersion = await this.storage.getLatestVersion(componentName); if (currentVersion === latestVersion) { utils_1.Logger.info(`Component ${componentName} is already up to date (${currentVersion})`); return; } // Check if the newer version is available for this platform/arch const targetPlatform = platform || process.platform; const targetArch = arch || process.arch; const exists = await this.storage.componentExists(componentName, latestVersion, targetPlatform, targetArch); if (!exists) { utils_1.Logger.warning(`Latest version ${latestVersion} of ${componentName} is not available for ${targetPlatform}-${targetArch}. Keeping current version ${currentVersion}.`); return; } utils_1.Logger.info(`Updating ${componentName} from ${currentVersion} to ${latestVersion}`); // Install the latest version await this.install(componentName, latestVersion, platform, arch); utils_1.Logger.success(`Successfully updated ${componentName} from ${currentVersion} to ${latestVersion}`); } catch (error) { utils_1.Logger.error(`Failed to check for updates for ${componentName}: ${error instanceof Error ? error.message : String(error)}`); utils_1.Logger.info(`Reinstalling current version ${currentVersion} instead...`); await this.install(componentName, currentVersion, platform, arch); } } else { // Update all components utils_1.Logger.info('Checking for updates for all installed components...'); const components = await utils_1.ConfigManager.getComponentConfig(); const componentNames = Object.keys(components); if (componentNames.length === 0) { utils_1.Logger.info('No components installed to update'); return; } let updatedCount = 0; let errorCount = 0; for (const name of componentNames) { try { const currentVersion = components[name]; const latestVersion = await this.storage.getLatestVersion(name); if (currentVersion !== latestVersion) { utils_1.Logger.info(`Found update for ${name}: ${currentVersion}${latestVersion}`); await this.update(name, platform, arch); updatedCount++; } else { utils_1.Logger.debug(`${name} is already up to date (${currentVersion})`); } } catch (error) { utils_1.Logger.error(`Failed to update ${name}: ${error instanceof Error ? error.message : String(error)}`); errorCount++; } } if (updatedCount > 0) { utils_1.Logger.success(`Successfully updated ${updatedCount} component${updatedCount !== 1 ? 's' : ''}`); } else { utils_1.Logger.info('All components are already up to date'); } if (errorCount > 0) { utils_1.Logger.warning(`${errorCount} component${errorCount !== 1 ? 's' : ''} failed to update`); } } } async list() { const components = await utils_1.ConfigManager.getComponentConfig(); const componentInfos = []; for (const [name, version] of Object.entries(components)) { const componentDir = utils_1.PathUtils.getComponentDir(name); const installed = await utils_1.FileUtils.exists(componentDir); let size; if (installed) { try { const stats = await fs_extra_1.default.stat(componentDir); size = stats.size; } catch { // Ignore errors getting size } } componentInfos.push({ name, version, installed, path: installed ? componentDir : undefined, size }); } return componentInfos; } async getAvailableComponents(platform, arch) { try { const targetPlatform = platform || process.platform; const targetArch = arch || process.arch; utils_1.Logger.debug(`Fetching available components for ${targetPlatform}-${targetArch}...`); return await this.storage.getAvailableComponents(targetPlatform, targetArch); } catch (error) { utils_1.Logger.error(`Failed to fetch available components: ${error instanceof Error ? error.message : String(error)}`); throw new Error('Unable to fetch component registry'); } } async downloadComponent(component, version, outputDir) { try { const targetVersion = version || component.version; const downloadDir = outputDir || path_1.default.join(process.cwd(), 'downloads', component.name); utils_1.Logger.info(`Downloading ${component.name}@${targetVersion}...`); return await this.storage.downloadComponent(component, targetVersion, downloadDir); } catch (error) { utils_1.Logger.error(`Failed to download component ${component.name}: ${error instanceof Error ? error.message : String(error)}`); throw new Error(`Component download failed: ${error instanceof Error ? error.message : String(error)}`); } } async downloadAndExtractComponent(metadata, targetDir, platform, arch) { try { utils_1.Logger.info(`Installing ${metadata.name}@${metadata.version} for ${platform}-${arch}...`); // Use the storage strategy to download the component // This will handle GitHub releases and HTTP URLs const archivePath = await this.storage.downloadComponent(metadata, metadata.version, targetDir); // Extract the component if it's a real archive if (archivePath.endsWith('.zip')) { await this.downloader.extractComponent(archivePath, targetDir); // Clean up the archive file after extraction await utils_1.FileUtils.removeFile(archivePath); } // Create component metadata file const componentInfo = { name: metadata.name, version: metadata.version, description: metadata.description, platform, arch, downloadUrl: this.storage.buildDownloadUrl(metadata.name, metadata.version, platform, arch), installedAt: new Date().toISOString() }; await utils_1.FileUtils.writeJson(path_1.default.join(targetDir, 'component.json'), componentInfo); utils_1.Logger.debug(`Component ${metadata.name} installed to ${targetDir} for ${platform}-${arch}`); } catch (error) { utils_1.Logger.error(`Failed to download component: ${error instanceof Error ? error.message : String(error)}`); throw error; } } async checkForUpdates(componentName) { const components = await utils_1.ConfigManager.getComponentConfig(); const updateInfo = []; const componentsToCheck = componentName ? [componentName] : Object.keys(components); for (const name of componentsToCheck) { if (!components[name]) { if (componentName) { throw new Error(`Component ${componentName} is not installed`); } continue; } try { const currentVersion = components[name]; const latestVersion = await this.storage.getLatestVersion(name); const updateAvailable = currentVersion !== latestVersion; updateInfo.push({ name, currentVersion, latestVersion, updateAvailable }); } catch (error) { utils_1.Logger.warning(`Failed to check latest version for ${name}: ${error instanceof Error ? error.message : String(error)}`); // Add entry with unknown latest version updateInfo.push({ name, currentVersion: components[name], latestVersion: 'unknown', updateAvailable: false }); } } return updateInfo; } async clearCache() { utils_1.Logger.info('Clearing component download cache...'); await this.downloader.clearCache(); utils_1.Logger.success('Component cache cleared successfully'); } } exports.ComponentManager = ComponentManager; //# sourceMappingURL=component-manager.js.map