import { DataSource, DataSourceOptions } from 'typeorm'; import { Collection, Store, Logger, SmartCollection } from '../database/entity'; import { CollectionRepository, LoggerRepository, SmartCollectionRepository, StoreRepository } from '../database/repository'; import ConfigManager from './ConfigManager'; import { StorageType } from '../enums/StorageType'; export default class ConnectionManager { configManager: ConfigManager; options: DataSourceOptions[]; dataSource: DataSource; schemas: any[] = [Collection, Store, Logger, SmartCollection]; subscribers: any[] = []; migrations: any[] = []; omitables: any[] = ['title', 'description', 'enabled']; constructor(configManager: ConfigManager) { this.configManager = configManager; const allConnections: DataSourceOptions[] = this.configManager.get(StorageType.DatabaseConnections) || []; this.options = this.normalize(allConnections); this.registerEntities(this.options); this.registerSubscribers(this.options); this.registerMigrations(this.options); this.dataSource = new DataSource(this.getDefaultOptions(allConnections)); } getDefaultOptions(allConnections: DataSourceOptions[]): DataSourceOptions { // Prefer sqlite from enabled options, then from all connections as fallback. const fromEnabled = this.options.find((item: any) => item.type === 'better-sqlite3'); if (fromEnabled) return this.discardOmitables(fromEnabled); const fromAll = allConnections.find((item: any) => item.type === 'better-sqlite3'); if (fromAll) return this.discardOmitables({ ...fromAll, entities: this.schemas, subscribers: this.subscribers, migrations: this.migrations }); return this.discardOmitables(this.options[0]); } async initialize() { return await this.dataSource.initialize(); } async isInitialized() { return this.dataSource.isInitialized; } getDataSource(): DataSource { return this.dataSource; } createDataSource(options: DataSourceOptions) { return new DataSource(this.discardOmitables(options)).initialize(); } registerEntities(options: DataSourceOptions[]) { this.options = options.map((obj) => ({ ...obj, entities: this.schemas })); } registerSubscribers(options: DataSourceOptions[]) { this.options = options.map((obj) => ({ ...obj, subscribers: this.subscribers })); } registerMigrations(options: DataSourceOptions[]) { this.options = options.map((obj) => ({ ...obj, migrations: this.migrations })); } discardOmitables(options: object | any): object | any { return Object.fromEntries(Object.entries(options).filter(([key]) => !this.omitables.includes(key))); } normalize(options: DataSourceOptions[]) { return options.filter((item: DataSourceOptions) => this.discardOmitables(item)).filter((item: any) => item.enabled); } /** * Proxy methods */ getCollection() { return this.dataSource.getRepository(Collection); } getLogger() { return this.dataSource.getRepository(Logger); } getStore() { return this.dataSource.getRepository(Store); } getCollectionRepository() { return this.getCollection().extend(CollectionRepository); } getLoggerRepository() { return this.getLogger().extend(LoggerRepository); } getStoreRepository() { return this.getStore().extend(StoreRepository); } getSmartCollection() { return this.dataSource.getRepository(SmartCollection); } getSmartCollectionRepository() { return this.getSmartCollection().extend(SmartCollectionRepository); } }