import { BullModule } from '@nestjs/bull'; import { DynamicModule, Module, ModuleMetadata, Provider } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import * as admin from 'firebase-admin'; import { RefCode, RefCodeWhiteList, User, Wallet } from './database/entities'; import { FunkiIdDiscordService } from './funki-id-discord.service'; import { FunkiIdEvmService } from './funki-id-evm.service'; import { FunkiIdRedditService } from './funki-id-reddit.service'; import { FunkiIdSteamService } from './funki-id-steam.service'; import { FunkiIdTelegramService } from './funki-id-telegram.service'; import { FunkiIdXService } from './funki-id-x.service'; import { FunkiIdController } from './funki-id.controller'; import { FunkiIdService } from './funki-id.service'; import RedisLibModule from './libs/redis'; import { UserDeleteModule } from './modules/delete/delete.module'; export interface FirebaseModuleOptions { serviceAccount: admin.ServiceAccount; } export interface FunkiDiscordConfiguration { clientId: string; clientSecret: string; redirectUrl: string; } export interface FunkiRedditConfiguration { clientId: string; clientSecret: string; redirectUrl: string; } export interface FunkiSteamConfiguration { apiKey: string; redirectUrl: string; } export interface FunkiXConfiguration { bearerToken: string; } export interface FunkiIdModuleOptions { isProduction: boolean; firebaseServiceAccount: FirebaseModuleOptions['serviceAccount']; redisUrl: string; postgresUrl: string; telegramBotToken: string; discordConfig: FunkiDiscordConfiguration; steamConfig: FunkiSteamConfiguration; redditConfig: FunkiRedditConfiguration; xConfig: FunkiXConfiguration; } export interface FunkiIdModuleAsyncOptions extends Pick { useFactory: (...args: any[]) => Promise | FunkiIdModuleOptions; inject?: any[]; } @Module({}) export class FunkiIdModule { static forRoot(options: FunkiIdModuleOptions): DynamicModule { return this.createModule({ useFactory: () => options, }); } static forRootAsync(options: FunkiIdModuleAsyncOptions): DynamicModule { return this.createModule(options); } private static createModule(options: FunkiIdModuleAsyncOptions): DynamicModule { const providers = this.createProviders(options); return { global: true, module: FunkiIdModule, imports: [...(options.imports || [])], providers, exports: [...providers], }; } private static createProviders(options: FunkiIdModuleAsyncOptions): Provider[] { const optionsProvider: Provider = { provide: 'FUNKI_ID_MODULE_OPTIONS', useFactory: options.useFactory, inject: options.inject || [], }; const firebaseAdminProvider: Provider = { provide: 'FIREBASE_ADMIN', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => { const app = admin.initializeApp({ credential: admin.credential.cert(funkiIdOptions.firebaseServiceAccount), }); return app; }, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const firebaseAuthProvider: Provider = { provide: 'FIREBASE_AUTH', useFactory: (app: admin.app.App) => app.auth(), inject: ['FIREBASE_ADMIN'], }; const redisProvider: Provider = { provide: RedisLibModule, useFactory: (funkiIdOptions: FunkiIdModuleOptions) => { return RedisLibModule.registerAsync({ useFactory: async () => { return { url: funkiIdOptions.redisUrl }; }, }); }, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const telegramBotTokenProvider: Provider = { provide: 'TELEGRAM_BOT_TOKEN', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => funkiIdOptions.telegramBotToken, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const discordConfigProvider: Provider = { provide: 'DISCORD_CONFIG', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => funkiIdOptions.discordConfig, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const steamConfigProvider: Provider = { provide: 'STEAM_CONFIG', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => funkiIdOptions.steamConfig, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const redditConfigProvider: Provider = { provide: 'REDDIT_CONFIG', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => funkiIdOptions.redditConfig, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const xConfigProvider: Provider = { provide: 'X_CONFIG', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => funkiIdOptions.xConfig, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; const envProvider: Provider = { provide: 'ENV_CONFIG', useFactory: (funkiIdOptions: FunkiIdModuleOptions) => { return { isProduction: funkiIdOptions.isProduction }; }, inject: ['FUNKI_ID_MODULE_OPTIONS'], }; return [ optionsProvider, firebaseAdminProvider, firebaseAuthProvider, redisProvider, telegramBotTokenProvider, discordConfigProvider, steamConfigProvider, redditConfigProvider, xConfigProvider, envProvider, ]; } static forFeature(): DynamicModule { return { global: true, module: FunkiIdModule, imports: [ TypeOrmModule.forFeature([User, Wallet, RefCode, RefCodeWhiteList], 'funki-id'), UserDeleteModule, BullModule.registerQueue({ name: 'validate-quest-by-type-queue', defaultJobOptions: { removeOnComplete: 10, removeOnFail: 10, }, }), ], providers: [ FunkiIdService, FunkiIdEvmService, FunkiIdTelegramService, FunkiIdDiscordService, FunkiIdSteamService, FunkiIdRedditService, FunkiIdXService, ], controllers: [FunkiIdController], exports: [ FunkiIdService, FunkiIdEvmService, FunkiIdTelegramService, FunkiIdDiscordService, FunkiIdSteamService, FunkiIdRedditService, FunkiIdXService, ], }; } }