import { Injectable, OnModuleDestroy, ServiceUnavailableException, } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import mysql, { Pool, PoolOptions, RowDataPacket } from 'mysql2/promise'; @Injectable() export class LegacyMysqlService implements OnModuleDestroy { private pool: Pool | null = null; constructor(private readonly config: ConfigService) {} async onModuleDestroy() { if (this.pool) { await this.pool.end(); this.pool = null; } } isConfigured(): boolean { return Boolean( this.config.get('OLD_MYSQL_HOST') && this.config.get('OLD_MYSQL_USER') && this.config.get('OLD_MYSQL_DATABASE'), ); } async query( sql: string, params: unknown[] = [], ): Promise { const pool = this.getPool(); try { const [rows] = await pool.query(sql, params); return rows; } catch (err) { const message = err instanceof Error ? err.message : 'Unknown MySQL error'; throw new ServiceUnavailableException( `Old CMS MySQL query failed: ${message}. Ensure the SSH tunnel is up and OLD_MYSQL_* is set.`, ); } } private getPool(): Pool { if (this.pool) { return this.pool; } if (!this.isConfigured()) { throw new ServiceUnavailableException( 'Old CMS MySQL is not configured. Set OLD_MYSQL_HOST, OLD_MYSQL_USER, OLD_MYSQL_DATABASE (and password/port).', ); } const options: PoolOptions = { host: this.config.getOrThrow('OLD_MYSQL_HOST'), port: Number(this.config.get('OLD_MYSQL_PORT', '3307')), user: this.config.getOrThrow('OLD_MYSQL_USER'), password: this.config.get('OLD_MYSQL_PASSWORD', ''), database: this.config.getOrThrow('OLD_MYSQL_DATABASE'), waitForConnections: true, connectionLimit: 4, namedPlaceholders: false, }; this.pool = mysql.createPool(options); return this.pool; } }