import { BaseMigration } from './base-migration.ts'; import { logger } from '../logger.ts'; /** * Migration from v4.1 to v4.2 * * Major changes: * 1. Moves thresholds from UPS level to action level * 2. Creates default shutdown action for UPS devices that had thresholds * 3. Adds empty actions array to UPS devices without actions * 4. Adds empty actions array to groups * * Transforms v4.1 format (with UPS-level thresholds): * { * version: "4.1", * upsDevices: [ * { * id: "ups-1", * name: "UPS 1", * snmp: {...}, * thresholds: { battery: 60, runtime: 20 }, // UPS-level * groups: [], * actions: [] * } * ] * } * * To v4.2 format (with action-level thresholds): * { * version: "4.2", * upsDevices: [ * { * id: "ups-1", * name: "UPS 1", * snmp: {...}, * groups: [], * actions: [ // Thresholds moved here * { * type: "shutdown", * thresholds: { battery: 60, runtime: 20 }, * triggerMode: "onlyThresholds", * shutdownDelay: 5 * } * ] * } * ] * } */ export class MigrationV4_1ToV4_2 extends BaseMigration { readonly fromVersion = '4.1'; readonly toVersion = '4.2'; async shouldRun(config: any): Promise { // Run if config is version 4.1 if (config.version === '4.1') { return true; } // Also run if config has upsDevices with thresholds at UPS level (v4.1 format) if (config.upsDevices && config.upsDevices.length > 0) { const firstDevice = config.upsDevices[0]; // v4.1 has thresholds at UPS level, v4.2 has them in actions return firstDevice.thresholds !== undefined; } return false; } async migrate(config: any): Promise { logger.info(`${this.getName()}: Migrating v4.1 config to v4.2 format...`); logger.dim(` - Moving thresholds from UPS level to action level`); logger.dim(` - Creating default shutdown actions from existing thresholds`); // Migrate UPS devices const migratedDevices = (config.upsDevices || []).map((device: any) => { const migrated: any = { id: device.id, name: device.name, snmp: device.snmp, groups: device.groups || [], }; // If device has thresholds at UPS level, convert to shutdown action if (device.thresholds) { migrated.actions = [ { type: 'shutdown', thresholds: { battery: device.thresholds.battery, runtime: device.thresholds.runtime, }, triggerMode: 'onlyThresholds', // Preserve old behavior (only on threshold violation) shutdownDelay: 5, // Default delay }, ]; logger.dim( ` → ${device.name}: Created shutdown action (battery: ${device.thresholds.battery}%, runtime: ${device.thresholds.runtime}min)`, ); } else { // No thresholds, just add empty actions array migrated.actions = device.actions || []; } return migrated; }); // Add actions to groups const migratedGroups = (config.groups || []).map((group: any) => ({ ...group, actions: group.actions || [], })); const result = { version: this.toVersion, upsDevices: migratedDevices, groups: migratedGroups, checkInterval: config.checkInterval || 30000, }; logger.success( `${this.getName()}: Migration complete (${migratedDevices.length} devices, ${migratedGroups.length} groups updated)`, ); return result; } }