Files
cmdb-insight/backend/src/services/database/factory.ts

86 lines
3.7 KiB
TypeScript

/**
* Database Factory
*
* Creates the appropriate database adapter based on environment configuration.
*/
import { logger } from '../logger.js';
import { PostgresAdapter } from './postgresAdapter.js';
import { SqliteAdapter } from './sqliteAdapter.js';
import type { DatabaseAdapter } from './interface.js';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Create a database adapter based on environment variables
* @param allowClose - If false, the adapter won't be closed when close() is called (for singletons)
*/
export function createDatabaseAdapter(dbType?: string, dbPath?: string, allowClose: boolean = true): DatabaseAdapter {
const type = dbType || process.env.DATABASE_TYPE || 'sqlite';
const databaseUrl = process.env.DATABASE_URL;
if (type === 'postgres' || type === 'postgresql') {
if (!databaseUrl) {
// Try to construct from individual components
const host = process.env.DATABASE_HOST || 'localhost';
const port = process.env.DATABASE_PORT || '5432';
const name = process.env.DATABASE_NAME || 'cmdb';
const user = process.env.DATABASE_USER || 'cmdb';
const password = process.env.DATABASE_PASSWORD || '';
// Azure PostgreSQL requires SSL - always use sslmode=require for Azure
const isAzure = host.includes('.postgres.database.azure.com');
const ssl = (process.env.DATABASE_SSL === 'true' || isAzure) ? '?sslmode=require' : '';
const constructedUrl = `postgresql://${user}:${password}@${host}:${port}/${name}${ssl}`;
logger.info('Creating PostgreSQL adapter with constructed connection string');
logger.info(`Database: ${name}, SSL: ${ssl ? 'required' : 'not required'}`);
return new PostgresAdapter(constructedUrl, allowClose);
}
logger.info('Creating PostgreSQL adapter');
return new PostgresAdapter(databaseUrl, allowClose);
}
// Default to SQLite
const defaultPath = dbPath || join(__dirname, '../../data/cmdb-cache.db');
logger.info(`Creating SQLite adapter with path: ${defaultPath}`);
return new SqliteAdapter(defaultPath);
}
/**
* Create a database adapter for the classifications database
*/
export function createClassificationsDatabaseAdapter(): DatabaseAdapter {
const type = process.env.DATABASE_TYPE || 'sqlite';
const databaseUrl = process.env.CLASSIFICATIONS_DATABASE_URL || process.env.DATABASE_URL;
if (type === 'postgres' || type === 'postgresql') {
if (!databaseUrl) {
// Try to construct from individual components
const host = process.env.DATABASE_HOST || 'localhost';
const port = process.env.DATABASE_PORT || '5432';
const name = process.env.CLASSIFICATIONS_DATABASE_NAME || process.env.DATABASE_NAME || 'cmdb';
const user = process.env.DATABASE_USER || 'cmdb';
const password = process.env.DATABASE_PASSWORD || '';
// Azure PostgreSQL requires SSL - always use sslmode=require for Azure
const isAzure = host.includes('.postgres.database.azure.com');
const ssl = (process.env.DATABASE_SSL === 'true' || isAzure) ? '?sslmode=require' : '';
const constructedUrl = `postgresql://${user}:${password}@${host}:${port}/${name}${ssl}`;
logger.info('Creating PostgreSQL adapter for classifications with constructed connection string');
return new PostgresAdapter(constructedUrl);
}
logger.info('Creating PostgreSQL adapter for classifications');
return new PostgresAdapter(databaseUrl);
}
// Default to SQLite
const defaultPath = join(__dirname, '../../data/classifications.db');
logger.info(`Creating SQLite adapter for classifications with path: ${defaultPath}`);
return new SqliteAdapter(defaultPath);
}