import { Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; import { MongooseModule } from '@nestjs/mongoose'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AttachmentStorage, ChangeFeed, NotificationMailer, NotificationsRepository, FindActivityRepository, FindCommentsRepository, FindIssuesRepository, FindProjectsRepository, FindReleasesRepository, FindTimelineRepository, IssueNumbersRepository, ProjectKeysRepository, ReleaseIssuesRepository, ReleaseNamesRepository, TrackerStreamsRepository, UpsertMaterializedActivityRepository, UpsertMaterializedCommentRepository, UpsertMaterializedIssueRepository, UpsertMaterializedProjectRepository, UpsertMaterializedReleaseRepository, UpsertMaterializedTimelineRepository, UserDirectory, } from '@task-stream/api/tracker/application'; import { IdentityUserDirectory } from './identity/identity-user-directory'; import { MongoFindActivityRepository, MongoFindCommentsRepository, MongoFindIssuesRepository, MongoFindProjectsRepository, MongoFindReleasesRepository, MongoFindTimelineRepository, } from './mongo/find.repositories'; import { READ_MODEL_SCHEMAS } from './mongo/read-model.schemas'; import { MongoUpsertMaterializedActivityRepository, MongoUpsertMaterializedCommentRepository, MongoUpsertMaterializedIssueRepository, MongoUpsertMaterializedProjectRepository, MongoUpsertMaterializedReleaseRepository, MongoUpsertMaterializedTimelineRepository, } from './mongo/upsert-materialized.repositories'; import { StatusCategoryBackfill } from './mongo/status-category.backfill'; import { LOOKUP_ENTITIES } from './postgres/lookup.entities'; import { PostgresIssueNumbersRepository, PostgresProjectKeysRepository, PostgresReleaseNamesRepository, } from './postgres/lookup.repositories'; import { PostgresReleaseIssuesRepository } from './postgres/release-issues.repository'; import { PostgresTrackerStreamsRepository } from './postgres/tracker-streams.repository'; import { RedisChangeFeed } from './realtime/redis-change-feed'; import { MongoNotificationsRepository } from './mongo/notifications.repository'; import { SmtpNotificationMailer } from './mail/smtp-notification.mailer'; import { FileSystemAttachmentStorage } from './storage/file-system-attachment.storage'; const PORTS = [ // Write side lookups → PostgreSQL (aggregates themselves live in the event store) { provide: ProjectKeysRepository, useClass: PostgresProjectKeysRepository }, { provide: IssueNumbersRepository, useClass: PostgresIssueNumbersRepository }, { provide: ReleaseNamesRepository, useClass: PostgresReleaseNamesRepository }, { provide: ReleaseIssuesRepository, useClass: PostgresReleaseIssuesRepository, }, { provide: TrackerStreamsRepository, useClass: PostgresTrackerStreamsRepository, }, // Read side → MongoDB { provide: FindProjectsRepository, useClass: MongoFindProjectsRepository }, { provide: FindIssuesRepository, useClass: MongoFindIssuesRepository }, { provide: FindCommentsRepository, useClass: MongoFindCommentsRepository }, { provide: FindReleasesRepository, useClass: MongoFindReleasesRepository }, { provide: FindActivityRepository, useClass: MongoFindActivityRepository }, { provide: FindTimelineRepository, useClass: MongoFindTimelineRepository }, { provide: UpsertMaterializedProjectRepository, useClass: MongoUpsertMaterializedProjectRepository, }, { provide: UpsertMaterializedIssueRepository, useClass: MongoUpsertMaterializedIssueRepository, }, { provide: UpsertMaterializedCommentRepository, useClass: MongoUpsertMaterializedCommentRepository, }, { provide: UpsertMaterializedReleaseRepository, useClass: MongoUpsertMaterializedReleaseRepository, }, { provide: UpsertMaterializedActivityRepository, useClass: MongoUpsertMaterializedActivityRepository, }, { provide: UpsertMaterializedTimelineRepository, useClass: MongoUpsertMaterializedTimelineRepository, }, // Attached files → disk (ATTACHMENTS_DIR) { provide: AttachmentStorage, useClass: FileSystemAttachmentStorage }, // Notifications → MongoDB (per person), copies by e-mail → SMTP (optional) { provide: NotificationsRepository, useClass: MongoNotificationsRepository }, { provide: NotificationMailer, useClass: SmtpNotificationMailer }, // Realtime → Redis pub/sub { provide: ChangeFeed, useClass: RedisChangeFeed }, // Identity context (anti-corruption layer) { provide: UserDirectory, useClass: IdentityUserDirectory }, ]; /** Driven adapters of the tracker context. */ @Module({ imports: [ CqrsModule, TypeOrmModule.forFeature(LOOKUP_ENTITIES), MongooseModule.forFeature(READ_MODEL_SCHEMAS), ], providers: [...PORTS, StatusCategoryBackfill], exports: PORTS.map((port) => port.provide), }) export class TrackerInfrastructureModule {}