import { MailerModule } from '@nestjs-modules/mailer' import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo' import { HttpModule } from '@nestjs/axios' import { RequestMethod } from '@nestjs/common' import { ConfigModule, ConfigService } from '@nestjs/config' import { GraphQLModule } from '@nestjs/graphql' import { JwtModule, JwtModuleOptions } from '@nestjs/jwt' import { ServeStaticModule } from '@nestjs/serve-static' import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm' import crypto from 'crypto' import { Request } from 'express-serve-static-core' import { IncomingHttpHeaders } from 'http' import { ConsoleModule } from 'nestjs-console' import { LoggerModule, Params as LoggerModuleParams } from 'nestjs-pino' import { join } from 'path' import { serializeError } from 'serialize-error' import { entities } from './entity' export const LoggerConfig: LoggerModuleParams = { pinoHttp: { level: process.env.CLI ? 'warn' : process.env.NODE_ENV !== 'production' ? 'debug' : 'info', serializers: { error: serializeError, }, transport: process.env.NODE_ENV !== 'production' || process.env.CLI ? { options: { ignore: 'req,res,pid,hostname', translateTime: true, }, target: 'pino-pretty', } : undefined, }, exclude: [ { method: RequestMethod.ALL, path: '_health', }, { method: RequestMethod.ALL, path: 'favicon.ico', }, ], } export const imports = [ ConsoleModule, HttpModule.register({ timeout: 5000, maxRedirects: 10, }), ServeStaticModule.forRoot({ rootPath: join(__dirname, '..', 'public'), exclude: ['/graphql'], }), ConfigModule.forRoot({ load: [ () => { return { LOCALES_PATH: join(process.cwd(), 'locales'), SECRET_KEY: process.env.SECRET_KEY || crypto.randomBytes(20).toString('hex'), } }, ], }), JwtModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService): JwtModuleOptions => ({ secret: configService.get('SECRET_KEY'), signOptions: { expiresIn: '4h', }, }), }), LoggerModule.forRoot(LoggerConfig), GraphQLModule.forRoot({ debug: process.env.NODE_ENV !== 'production', definitions: { outputAs: 'class', }, driver: ApolloDriver, sortSchema: true, introspection: process.env.NODE_ENV !== 'production', playground: process.env.NODE_ENV !== 'production', installSubscriptionHandlers: true, autoSchemaFile: join(process.cwd(), 'src/schema.gql'), // to allow guards on resolver props https://github.com/nestjs/graphql/issues/295 fieldResolverEnhancers: [ 'guards', 'interceptors', ], resolverValidationOptions: { }, context: ({ req, connection }) => { if (!req && connection) { const headers: IncomingHttpHeaders = {} Object.keys(connection.context).forEach(key => { headers[key.toLowerCase()] = connection.context[key] }) return { req: { headers, } as Request, } } return { req } }, }), TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService): TypeOrmModuleOptions => { const type: any = configService.get('DATABASE_DRIVER', 'sqlite') let migrationFolder: string let migrationsTransactionMode: 'each' | 'none' | 'all' = 'each' switch (type) { case 'cockroachdb': case 'postgres': migrationFolder = 'postgres' break case 'mysql': case 'mariadb': migrationFolder = 'mariadb' break case 'sqlite': migrationFolder = 'sqlite' migrationsTransactionMode = 'none' break default: throw new Error('unsupported driver') } return ({ name: 'ohmyform', synchronize: false, type, url: configService.get('DATABASE_URL'), database: type === 'sqlite' ? configService.get('DATABASE_URL', 'data.sqlite').replace('sqlite://', '') : undefined, ssl: configService.get('DATABASE_SSL', 'false') === 'true' ? { rejectUnauthorized: false } : false, entityPrefix: configService.get('DATABASE_TABLE_PREFIX', ''), logging: configService.get('DATABASE_LOGGING', 'false') === 'true', entities, migrations: [`${__dirname}/**/migrations/${migrationFolder}/**/*{.ts,.js}`], migrationsRun: configService.get('DATABASE_MIGRATE', true), migrationsTransactionMode, }) }, }), TypeOrmModule.forFeature(entities), MailerModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ transport: configService.get('MAILER_URI', 'smtp://localhost:1025'), defaults: { from: configService.get('MAILER_FROM', 'OhMyForm '), }, }), }), ]