import { DynamicModule } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { EntityClassOrSchema } from '@nestjs/typeorm/dist/interfaces/entity-class-or-schema.type'; import { AppConfigDataRDB, ConfigProviderService, LoggerService, RDBType, loadDynamicModules } from '@node-c/core'; import { SQLQueryBuilderModule } from '@node-c/data-rdb'; import { DataSource } from 'typeorm'; import { TypeORMDBModuleOptions } from './typeorm.module.definitions'; export class TypeORMDBModule { static register(options: TypeORMDBModuleOptions): DynamicModule { const { connectionName, folderData, imports: additionalImports, moduleClass, moduleName } = options; const { atEnd: importsAtEnd, postORM: importsPostORM, preORM: importsPreORM } = additionalImports || {}; const { entities, modules } = loadDynamicModules(folderData, { moduleRegisterOptions: options.entityModuleRegisterOptions, registerOptionsPerModule: options.registerOptionsPerEntityModule }); let lastRetryAt = new Date().valueOf(); return { global: true, module: moduleClass as DynamicModule['module'], imports: [ ...(importsPreORM || []), TypeOrmModule.forRootAsync({ dataSourceFactory: async options => { const { failOnConnectionError = true, nodeCAppLoggerService } = (options || {}) as { failOnConnectionError?: boolean; nodeCAppLoggerService: LoggerService; }; let dataSource: DataSource; try { nodeCAppLoggerService.info(`[TypeORMDBModule][${moduleName}]: Connecting to the DB server...`); dataSource = new DataSource(options!); await dataSource.initialize(); nodeCAppLoggerService.info(`[TypeORMDBModule][${moduleName}]: Connected to the DB server successfully.`); } catch (err) { nodeCAppLoggerService.error(`[TypeORMDBModule][${moduleName}]: Error connecting to the DB server:`, err); if (failOnConnectionError) { throw err; } } return dataSource!; }, name: connectionName, useFactory: (configProvider: ConfigProviderService, logger: LoggerService) => { const dataConfig = configProvider.config.data; // example : configProvider.config.data.db const { database, failOnConnectionError, host, password, port, type, typeormExtraOptions, user } = dataConfig[moduleName as keyof typeof dataConfig] as AppConfigDataRDB; const dataSourceOptions: { toRetry?: TypeOrmModuleOptions['toRetry'] } = {}; if (!failOnConnectionError) { dataSourceOptions.toRetry = () => { const now = new Date().valueOf(); // 1 minute retry interval if (Math.abs(lastRetryAt - now) > 60000) { lastRetryAt = now; return true; } return false; }; } return { ...dataSourceOptions, database, entities: entities as EntityClassOrSchema[], failOnConnectionError, host, manualInitialization: true, name: connectionName, nodeCAppLoggerService: logger, password, port, synchronize: false, type: type === RDBType.Aurora ? RDBType.MySQL : type, username: user, ...(typeormExtraOptions || {}) } as TypeOrmModuleOptions; }, inject: [ConfigProviderService, LoggerService] }), SQLQueryBuilderModule.register({ dataModuleName: moduleName }), ...(importsPostORM || []), ...(modules || []), ...(importsAtEnd || []) ], providers: [...(options.providers || [])], exports: [...(modules || []), ...(options.exports || [])] }; } }