feat: implement database service with SQL Server and MySQL support

- Add database types (QueryResult, TransactionResult)
- Implement DatabaseService with connection management for SQL Server and MySQL
- Add query execution methods for both database types
- Include comprehensive error handling and logging
- Add unit test for error handling
- Configure Jest for testing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-02-28 22:28:02 +08:00
parent 7cfbce7505
commit 351c7857cb
4 changed files with 152 additions and 0 deletions

8
jest.config.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/tests'],
testMatch: ['**/*.test.ts'],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts'],
moduleFileExtensions: ['ts', 'js', 'json'],
};

View File

@@ -0,0 +1,9 @@
export interface QueryResult {
rows: any[];
rowCount: number;
}
export interface TransactionResult {
success: boolean;
rowsAffected: number;
}

View File

@@ -0,0 +1,109 @@
import sql from 'mssql';
import mysql from 'mysql2/promise';
import { SQLServerConfig, MySQLConfig } from '../models/config.types';
import { QueryResult } from '../models/database.types';
import { LoggerService } from './logger.service';
export class DatabaseService {
private sqlServerPool?: sql.ConnectionPool;
private mysqlPool?: mysql.Pool;
constructor(
private sqlServerConfig: SQLServerConfig,
private mysqlConfig: MySQLConfig
) {}
async connectToSQLServer(): Promise<void> {
try {
LoggerService.info('Connecting to SQL Server...');
this.sqlServerPool = await sql.connect({
server: this.sqlServerConfig.server,
database: this.sqlServerConfig.database,
user: this.sqlServerConfig.username,
password: this.sqlServerConfig.password,
driver: this.sqlServerConfig.driver,
options: {
trustServerCertificate:
this.sqlServerConfig.trustServerCertificate === 'yes',
},
});
LoggerService.info('SQL Server connection established');
} catch (error) {
LoggerService.error('Failed to connect to SQL Server', error);
throw error;
}
}
async connectToMySQL(): Promise<void> {
try {
LoggerService.info('Connecting to MySQL...');
this.mysqlPool = mysql.createPool({
host: this.mysqlConfig.host,
port: this.mysqlConfig.port,
database: this.mysqlConfig.database,
user: this.mysqlConfig.username,
password: this.mysqlConfig.password,
});
LoggerService.info('MySQL connection established');
} catch (error) {
LoggerService.error('Failed to connect to MySQL', error);
throw error;
}
}
async executeSQLServerQuery(query: string, params?: any[]): Promise<QueryResult> {
if (!this.sqlServerPool) {
throw new Error('SQL Server not connected');
}
try {
const request = this.sqlServerPool.request();
if (params) {
params.forEach((param, index) => {
request.input(`param${index}`, param);
});
}
const result = await request.query(query);
return {
rows: result.recordset,
rowCount: result.rowsAffected[0],
};
} catch (error) {
LoggerService.error('SQL Server query failed', { query, error });
throw error;
}
}
async executeMySQLQuery(query: string, params?: any[]): Promise<QueryResult> {
if (!this.mysqlPool) {
throw new Error('MySQL not connected');
}
try {
const [rows] = await this.mysqlPool.execute(query, params);
return {
rows: rows as any[],
rowCount: (rows as any[]).length,
};
} catch (error) {
LoggerService.error('MySQL query failed', { query, error });
throw error;
}
}
async closeAll(): Promise<void> {
if (this.sqlServerPool) {
await this.sqlServerPool.close();
LoggerService.info('SQL Server connection closed');
}
if (this.mysqlPool) {
await this.mysqlPool.end();
LoggerService.info('MySQL connection closed');
}
}
}

View File

@@ -0,0 +1,26 @@
import { DatabaseService } from '../../../src/main/services/database.service';
describe('DatabaseService', () => {
it('should throw error when querying without connection', async () => {
const service = new DatabaseService(
{
server: 'localhost',
database: 'test',
username: 'test',
password: 'test',
driver: 'test',
},
{
host: 'localhost',
port: 3306,
database: 'test',
username: 'test',
password: 'test',
}
);
await expect(
service.executeSQLServerQuery('SELECT 1')
).rejects.toThrow('SQL Server not connected');
});
});