import { DynamicModule , Global } from '@nestjs/common' ; import { Sequelize } from 'sequelize' ; import { Options as SequelizeOption } from 'sequelize/types' ; import * as entities from '../entities' ; import { getLogger } from '../utils/logger' ; import { delay } from '../utils/promise' ; import { getYargsOption } from '../yargs' ; export interface DbOption { host : string ; port : number ; username : string ; password : string ; database : string ; } const logger = getLogger ( 'db' ) ; async function establishConnection ( sequelize , numRetries ) { try { await sequelize . authenticate ( ) ; } catch ( error ) { logger . error ( error , 'Unable to connect to the database' ) ; if ( numRetries > 0 ) { await delay ( 3 ) ; void ( await establishConnection ( sequelize , numRetries - 1 ) ) ; } else { process . exit ( 1 ) ; } } } const sequelizeFactory = ( option ) => async ( ) => { const sequelize = new Sequelize ( option ) ; const numRetries = 5 ; await establishConnection ( sequelize , numRetries ) ; for ( const factoryFn of Object . keys ( entities ) . filter ( ( k ) => /Factory$/ . exec ( k ) ) ) { entities [ factoryFn ] ( sequelize ) ; } const { migrate } = getYargsOption ( ) . argv ; await sequelize . sync ( { alter : migrate } ) ; return sequelize ; } ; @ Global ( ) export class DbModule { static forRoot ( option ) { const { argv } = getYargsOption ( ) ; const logger = getLogger ( 'db' ) ; return { module : DbModule , providers : [ { provide : Sequelize , useFactory : sequelizeFactory ( { ... option , dialect : 'postgres' , logging : argv . debug ? ( sql , timing ? ) => { logger . debug ( sql ) ; } : false , } ) , } , ] , exports : [ Sequelize ] , } ; } static forFeature ( models ) { return { module : DbModule , providers : models . map ( ( model ) => ( { provide : model , inject : [ Sequelize ] , useFactory : ( sequelize ) => sequelize . model ( model ) , } ) ) , exports : models , } ; } }