import { Module } from '@nestjs/common'; import { APP_FILTER } from '@nestjs/core'; import { LoggerModule } from 'nestjs-pino'; import { AdminModule } from './admin/admin.module'; import { AuditModule } from './audit/audit.module'; import { AuthModule } from './auth/auth.module'; import { BackupModule } from './backup/backup.module'; import { ApiExceptionFilter } from './common/api-exception.filter'; import { CommentsModule } from './comments/comments.module'; import { CompactionModule } from './compaction/compaction.module'; import { AppConfig } from './config/app-config.service'; import { ConfigModule } from './config/config.module'; import { FilesModule } from './files/files.module'; import { GrantsModule } from './grants/grants.module'; import { HealthModule } from './health/health.module'; import { HomeModule } from './home/home.module'; import { ImportExportModule } from './import-export/import-export.module'; import { LabelsModule } from './labels/labels.module'; import { LegalModule } from './legal/legal.module'; import { LinksModule } from './links/links.module'; import { MailModule } from './mail/mail.module'; import { McpModule } from './mcp/mcp.module'; import { MembersModule } from './members/members.module'; import { PagesModule } from './pages/pages.module'; import { PermissionsModule } from './permissions/permissions.module'; import { PluginsModule } from './plugins/plugins.module'; import { PondsModule } from './ponds/ponds.module'; import { PrismaModule } from './prisma/prisma.module'; import { PublicApiModule } from './public-api/public-api.module'; import { PublicModule } from './public/public.module'; import { RateLimitModule } from './rate-limit/rate-limit.module'; import { SearchModule } from './search/search.module'; import { SettingsModule } from './settings/settings.module'; import { SetupModule } from './setup/setup.module'; import { TrashModule } from './trash/trash.module'; import { UsersModule } from './users/users.module'; import { NotificationsModule } from './notifications/notifications.module'; import { WatchesModule } from './watches/watches.module'; import { FavoritesModule } from './favorites/favorites.module'; import { VersionsModule } from './versions/versions.module'; @Module({ imports: [ ConfigModule, PrismaModule, AuditModule, RateLimitModule, MailModule, SettingsModule, // Before SetupModule and AuthModule: global guards run in registration // order, and the maintenance gate (in-app restore, issue #103) must // answer before anything touches the mid-restore database. BackupModule, // Before AuthModule: the setup gate must win over AuthGuard's 401 while // setup is pending. SetupModule, UsersModule, PermissionsModule, PondsModule, PagesModule, CommentsModule, WatchesModule, FavoritesModule, NotificationsModule, FilesModule, TrashModule, CompactionModule, VersionsModule, LabelsModule, LegalModule, HomeModule, LinksModule, SearchModule, GrantsModule, MembersModule, PublicModule, PublicApiModule, McpModule, ImportExportModule, PluginsModule, AuthModule, AdminModule, LoggerModule.forRootAsync({ inject: [AppConfig], useFactory: (config: AppConfig) => ({ pinoHttp: { level: config.env.LOG_LEVEL, // Human-readable logs in local development, JSON everywhere else. transport: config.env.NODE_ENV === 'development' ? { target: 'pino-pretty' } : undefined, autoLogging: config.env.NODE_ENV !== 'test', // Request bodies are never logged (operations.md logging rules). redact: { paths: ['req.headers.authorization', 'req.headers.cookie'], remove: true }, }, }), }), HealthModule, ], providers: [{ provide: APP_FILTER, useClass: ApiExceptionFilter }], }) export class AppModule {}