ableton-mcp-server-rag
Version:
Ableton Live MCP depend on Ableton JS
125 lines • 5.5 kB
JavaScript
import 'reflect-metadata';
import { DataSource } from 'typeorm';
import { OperationHistory } from './entities/OperationHistory.js';
import { Snapshot } from './entities/Snapshot.js';
import { logger } from './main.js';
import path from 'path';
import { createBackup, ensureMigrationsDir, isFirstRun } from './utils/migration-helper.js';
let AppDataSource = null;
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000; // 1 second delay
// 根据环境设置 TypeORM 日志级别
const isProd = process.env.NODE_ENV === 'production';
const typeormLogging = isProd
? ['error', 'warn', 'migration']
: ['query', 'error', 'schema', 'warn', 'info', 'log', 'migration'];
class TypeOrmLoggerAdapter {
logQuery(query, parameters) {
logger.debug(`[typeorm][query] ${query}${parameters && parameters.length ? ' -- ' + JSON.stringify(parameters) : ''}`);
}
logQueryError(error, query, parameters) {
logger.error(`[typeorm][query-error] ${query}${parameters && parameters.length ? ' -- ' + JSON.stringify(parameters) : ''} -- ${error}`);
}
logQuerySlow(time, query, parameters) {
logger.warn(`[typeorm][slow-query][${time}ms] ${query}${parameters && parameters.length ? ' -- ' + JSON.stringify(parameters) : ''}`);
}
logSchemaBuild(message) {
logger.info(`[typeorm][schema] ${message}`);
}
logMigration(message) {
logger.info(`[typeorm][migration] ${message}`);
}
log(level, message) {
if (level === 'log' || level === 'info') {
logger.info(`[typeorm][${level}] ${message}`);
}
else if (level === 'warn') {
logger.warn(`[typeorm][warn] ${message}`);
}
}
}
export async function initializeDataSource(dbPath) {
if (AppDataSource && AppDataSource.isInitialized) {
logger.info('Data Source has already been initialized!');
return;
}
logger.info(`Initializing Data Source with database path: ${dbPath}`);
// Check if this is the first run with the new migration system
const firstRun = isFirstRun(dbPath);
// Ensure migrations directory exists and get its path
const migrationsDir = ensureMigrationsDir();
AppDataSource = new DataSource({
type: 'sqljs',
location: dbPath,
autoSave: true,
useLocalForage: false,
// On first run, we can use synchronize to create tables
// After that, migrations will handle schema changes
synchronize: firstRun,
logging: typeormLogging,
logger: new TypeOrmLoggerAdapter(),
entities: [OperationHistory, Snapshot],
// Use the migrations directory path returned by ensureMigrationsDir
migrations: [path.join(migrationsDir, '*.js')],
migrationsTableName: 'migrations',
// Set to false, we will manually control the migration process
migrationsRun: false,
});
let retries = 0;
while (retries < MAX_RETRIES) {
try {
await AppDataSource.initialize();
// Only execute migrations and create backups when needed
if (!firstRun) {
// Debug - print migrations table content
try {
const migrationRows = await AppDataSource.query('SELECT * FROM migrations');
logger.info(`Current migrations in DB: ${JSON.stringify(migrationRows)}`);
}
catch (err) {
logger.warn('Could not query migrations table:', err);
}
// Check if there are pending migrations
// showMigrations() returns true if there are pending migrations
const hasPendingMigrations = await AppDataSource.showMigrations();
logger.info(`Has pending migrations: ${hasPendingMigrations}`);
// If there are pending migrations, create backup and run migrations
if (hasPendingMigrations) {
logger.info('Pending migrations detected, creating backup...');
createBackup(dbPath);
logger.info('Running migrations...');
const migrations = await AppDataSource.runMigrations();
logger.info(`Executed ${migrations.length} migrations`);
}
else {
logger.info('No pending migrations, skipping backup and migration');
}
}
logger.info('Data Source has been initialized successfully!');
logger.info(`Database initialized with ${firstRun ? 'synchronize mode' : 'migrations mode'}`);
return;
}
catch (err) {
retries++;
if (retries >= MAX_RETRIES) {
logger.error('Failed to initialize Data Source after maximum retries:', err);
throw err;
}
logger.warn(`Data Source initialization failed, retrying (${retries}/${MAX_RETRIES})...`);
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
}
}
}
export function getDataSource() {
if (!AppDataSource || !AppDataSource.isInitialized) {
throw new Error('Data Source is not initialized');
}
return AppDataSource;
}
export function getOperationHistoryRepository() {
return getDataSource().getRepository(OperationHistory);
}
export function getSnapshotRepository() {
return getDataSource().getRepository(Snapshot);
}
//# sourceMappingURL=db.js.map