@interopio/desktop-cli
Version:
io.Connect Desktop Seed Repository CLI Tools
303 lines • 15.2 kB
JavaScript
;
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