import { CommonsModule } from './commons/commons.module'; import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { GraphQLModule } from '@nestjs/graphql'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppResolver } from './app.resolver'; import { AppService } from './app.service'; import { ProjectsModule } from './projects/projects.module'; import { ReposModule } from './repos/repos.module'; import { PipelinesModule } from './pipelines/pipelines.module'; import { PipelineTasksModule } from './pipeline-tasks/pipeline-tasks.module'; import configuration from './commons/config/configuration'; import { RedisModule } from 'nestjs-redis'; import { WebhooksModule } from './webhooks/webhooks.module'; import { RawBodyMiddleware } from './commons/middleware/raw-body.middleware'; import { GiteaWebhooksController } from './webhooks/gitea-webhooks.controller'; import { ParseBodyMiddleware } from './commons/middleware/parse-body.middleware'; import { LoggerModule } from 'nestjs-pino'; import { EtcdModule } from 'nestjs-etcd'; import pinoPretty from 'pino-pretty'; import { fromPairs, map, pipe, toPairs } from 'ramda'; @Module({ imports: [ ConfigModule.forRoot({ load: [configuration], }), LoggerModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => { const isDev = configService.get<'dev' | 'prod'>('env') === 'dev'; return { pinoHttp: { prettyPrint: isDev ? { levelFirst: true, } : false, prettifier: pinoPretty, }, }; }, inject: [ConfigService], }), TypeOrmModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ type: 'postgres', host: configService.get('db.postgres.host'), port: configService.get('db.postgres.port'), username: configService.get('db.postgres.username'), password: configService.get('db.postgres.password'), database: configService.get('db.postgres.database'), synchronize: true, autoLoadEntities: true, }), inject: [ConfigService], }), GraphQLModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ debug: configService.get('env') !== 'prod', playground: true, autoSchemaFile: true, installSubscriptionHandlers: true, context: ({ req, connection, ...args }) => { return connection ? { req: connection.context } : { req }; }, subscriptions: { onConnect: (connectionParams: Record) => { const connectionParamsWithLowerKeys = pipe( toPairs, map(([key, value]) => [key.toLowerCase(), value]), fromPairs, )(connectionParams); return { headers: connectionParamsWithLowerKeys, }; }, }, }), inject: [ConfigService], }), ProjectsModule, ReposModule, PipelinesModule, PipelineTasksModule, RedisModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ host: configService.get('db.redis.host', 'localhost'), port: configService.get('db.redis.port', 6379), password: configService.get('db.redis.password', ''), keyPrefix: configService.get('db.redis.prefix', 'fennec') + ':', }), inject: [ConfigService], }), EtcdModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ hosts: configService.get('db.etcd.hosts', 'localhost:2379'), }), inject: [ConfigService], }), WebhooksModule, CommonsModule, ], controllers: [AppController], providers: [AppService, AppResolver], }) export class AppModule implements NestModule { public configure(consumer: MiddlewareConsumer): void { consumer .apply(RawBodyMiddleware) .forRoutes(GiteaWebhooksController) .apply(ParseBodyMiddleware) .forRoutes('*'); } }