import type { DynamicModule } from '@nestjs/common'; import type { NestModuleDefinition } from '@rsdk/common.nestjs'; import { flatten } from 'lodash'; import type { IErrorsFormatter, IErrorsSender } from '../exceptions.handling'; import { GlobalExceptionsModule } from '../exceptions.handling'; import { HealthModule } from '../health/health.module'; import { MetricsModule } from '../metrics'; import type { PlatformExtendedOptions } from '../types'; import { isPrimaryTransport } from '../types'; import { ProtocolDetector } from './protocol.detector'; export class PlatformTransportModule { static forOptions(options: PlatformExtendedOptions): DynamicModule { return { imports: [ PlatformTransportModule.initProtocolDetector(options), PlatformTransportModule.initHealthchecks(options), PlatformTransportModule.initMetrics(options), PlatformTransportModule.initExceptionsHandling(options), ...PlatformTransportModule.getTransportModules(options), ], module: PlatformTransportModule, }; } private static getTransportModules( options: PlatformExtendedOptions, ): NestModuleDefinition[] { return ( options?.transports?.flatMap?.((transport) => { return transport.modules?.() ?? []; }) ?? [] ); } private static initProtocolDetector( options: PlatformExtendedOptions, ): DynamicModule { return { module: PlatformTransportModule, providers: [ { provide: ProtocolDetector, useValue: new ProtocolDetector(options.transports ?? []), }, ], global: true, exports: [ProtocolDetector], }; } private static initMetrics(options: PlatformExtendedOptions): DynamicModule { const transports = options.transports ?? ([] as any[]); return MetricsModule.forRoot({ controllers: transports .filter(isPrimaryTransport) .map((x) => x.getMetricsController()), }); } private static initHealthchecks( options: PlatformExtendedOptions, ): DynamicModule { const transports = options.transports ?? ([] as any[]); return HealthModule.forRoot({ controllers: transports .filter(isPrimaryTransport) .map((x) => x.getHealthController()), }); } private static initExceptionsHandling( options: PlatformExtendedOptions, ): DynamicModule { const transports = options.transports ?? []; return GlobalExceptionsModule.forRoot({ formatters: [ ...transports.map((x) => x.getErrorsFormatter()), ...(options.plugins?.map((x) => x.errorFormatter?.()) || []), ].filter((x): x is IErrorsFormatter => Boolean(x)), senders: [ ...transports.map((x) => x.getErrorsSender?.()), ...(options.plugins?.map((x) => x.errorSender?.()) || []), ].filter((x): x is IErrorsSender => Boolean(x)), transformers: [ ...flatten(transports.map((x) => x.getErrorTransformers())), ...flatten(options.plugins?.map((x) => x.errorTransformers?.() || [])), ], }); } }