Major type safety improvements throughout the codebase: - Updated DEFAULT_CONFIG version to 4.2 - Replaced 'any' with proper types in systemd.ts: * displaySingleUpsStatus now uses IUpsConfig and NupstSnmp types * Fixed legacy config handling to use proper IUpsConfig format * Removed inline 'any' type annotations - Replaced 'any' with proper types in daemon.ts: * emergencyUps now properly typed as { ups: IUpsConfig, status: ISnmpUpsStatus } * Exported IUpsStatus interface for reuse * Added ISnmpUpsStatus import to disambiguate from daemon's IUpsStatus - Replaced 'any' with Record<string, unknown> in migration system: * Updated BaseMigration abstract class signatures * Updated MigrationRunner.run() signature * Updated migration-v4.0-to-v4.1.ts to use proper types * Migrations use Record<string, unknown> because they deal with unknown config schemas that are being upgraded Benefits: - TypeScript now catches type errors at compile time - Would have caught the ups.thresholds bug earlier - Better IDE autocomplete and type checking - More maintainable and self-documenting code
76 lines
2.1 KiB
TypeScript
76 lines
2.1 KiB
TypeScript
import { BaseMigration } from './base-migration.ts';
|
|
import { MigrationV1ToV2 } from './migration-v1-to-v2.ts';
|
|
import { MigrationV3ToV4 } from './migration-v3-to-v4.ts';
|
|
import { MigrationV4_0ToV4_1 } from './migration-v4.0-to-v4.1.ts';
|
|
import { logger } from '../logger.ts';
|
|
|
|
/**
|
|
* Migration runner
|
|
*
|
|
* Discovers all available migrations, sorts them by order,
|
|
* and runs applicable migrations in sequence.
|
|
*/
|
|
export class MigrationRunner {
|
|
private migrations: BaseMigration[];
|
|
|
|
constructor() {
|
|
// Register all migrations here
|
|
this.migrations = [
|
|
new MigrationV1ToV2(),
|
|
new MigrationV3ToV4(),
|
|
new MigrationV4_0ToV4_1(),
|
|
// Add future migrations here (v4.3, v4.4, etc.)
|
|
];
|
|
|
|
// Sort by version order to ensure they run in sequence
|
|
this.migrations.sort((a, b) => a.getVersionOrder() - b.getVersionOrder());
|
|
}
|
|
|
|
/**
|
|
* Run all applicable migrations on the config
|
|
*
|
|
* @param config - Raw configuration object to migrate
|
|
* @returns Migrated configuration and whether migrations ran
|
|
*/
|
|
async run(
|
|
config: Record<string, unknown>,
|
|
): Promise<{ config: Record<string, unknown>; migrated: boolean }> {
|
|
let currentConfig = config;
|
|
let anyMigrationsRan = false;
|
|
|
|
for (const migration of this.migrations) {
|
|
const shouldRun = await migration.shouldRun(currentConfig);
|
|
|
|
if (shouldRun) {
|
|
// Only show "checking" message when we actually need to migrate
|
|
if (!anyMigrationsRan) {
|
|
logger.dim('Checking for required config migrations...');
|
|
}
|
|
logger.info(`Running ${migration.getName()}...`);
|
|
currentConfig = await migration.migrate(currentConfig);
|
|
anyMigrationsRan = true;
|
|
}
|
|
}
|
|
|
|
if (anyMigrationsRan) {
|
|
logger.success('Configuration migrations complete');
|
|
} else {
|
|
logger.success('config format ok');
|
|
}
|
|
|
|
return {
|
|
config: currentConfig,
|
|
migrated: anyMigrationsRan,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get all registered migrations
|
|
*
|
|
* @returns Array of all migrations sorted by order
|
|
*/
|
|
getMigrations(): BaseMigration[] {
|
|
return [...this.migrations];
|
|
}
|
|
}
|