import { DynamicModule, forwardRef, Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { RabbitMQModule } from "@golevelup/nestjs-rabbitmq"; import { TypeOrmModule } from "@nestjs/typeorm"; import { PAYMENT_EVENTS_DLX, PAYMENT_EVENTS_EXCHANGE, PAYMENT_QUEUES, PaymentService as PaymentServiceEnum, paymentServiceBindingPattern, } from "@edr/types"; import { ServiceAuthGuard } from "../../common/guards/service-auth.guard"; import { BillingModule } from "../billing/billing.module"; import { UserTradeAccessModule } from "../user-trade-access/user-trade-access.module"; // import { FirstMileModule } from "../first-mile/first-mile.module"; // import { TrainSchedulingModule } from "../train-scheduling/train-scheduling.module"; import { PaymentRefundEntity } from "./entities/payment-refund.entity"; import { PaymentWebhookEventEntity } from "./entities/payment-webhook-event.entity"; import { PaymentEntity } from "./entities/payment.entity"; import { InternalPaymentController } from "./internal-payment.controller"; import { PaymentClientService } from "./payment-client.service"; import { PaymentController } from "./payment.controller"; import { PaymentEventsConsumer } from "./payment-events.consumer"; import { PaymentRepository } from "./payment.repository"; import { PaymentService } from "./payment.service"; const FREIGHT_QUEUE = PAYMENT_QUEUES[PaymentServiceEnum.FREIGHT]; function rabbitMQImport(): DynamicModule[] { if (!process.env.PAYMENT_RABBITMQ_URL) return []; return [ RabbitMQModule.forRootAsync({ inject: [ConfigService], useFactory: (config: ConfigService) => ({ uri: config.get("rabbitmq.url") ?? process.env.PAYMENT_RABBITMQ_URL ?? "", exchanges: [ { name: PAYMENT_EVENTS_EXCHANGE, type: "topic", options: { durable: true } }, { name: PAYMENT_EVENTS_DLX, type: "topic", options: { durable: true } }, ], queues: [ { name: FREIGHT_QUEUE.dlq, exchange: PAYMENT_EVENTS_DLX, routingKey: paymentServiceBindingPattern(PaymentServiceEnum.FREIGHT), options: { durable: true }, }, ], prefetchCount: config.get("rabbitmq.prefetch") ?? 10, connectionInitOptions: { wait: false }, }), }), ]; } @Module({ imports: [ // CAC Bank's initiate SMSes an OTP and routinely takes >10s, so the old // 10s cap 502'd every CAC charge while the bank was still working — // orphaning an intent the payer had already been texted about. Matches // the passenger API's budget. HttpModule.register({ timeout: Number(process.env.PAYMENT_API_HTTP_TIMEOUT_MS) || 60_000, }), ConfigModule, UserTradeAccessModule, forwardRef(() => BillingModule), // forwardRef(() => TrainSchedulingModule), // FirstMileModule, TypeOrmModule.forFeature([ PaymentEntity, PaymentWebhookEventEntity, PaymentRefundEntity, ]), ...rabbitMQImport(), ], providers: [ PaymentRepository, PaymentService, PaymentClientService, PaymentEventsConsumer, ServiceAuthGuard, ], controllers: [PaymentController, InternalPaymentController], exports: [PaymentService], }) export class PaymentModule {}