apps/api boots a NestJS application with: Zod-validated environment configuration (schema in @dorfteich/shared, fails fast listing every invalid variable), structured pino request logging via nestjs-pino (pretty in development, JSON otherwise, auth headers redacted), a global exception filter producing the uniform ApiErrorBody shape, and GET /api/v1/healthz. Vitest runs Nest through SWC for decorator metadata; supertest covers healthz and the 404 error shape. Closes #2 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { APP_FILTER } from '@nestjs/core';
|
|
import { LoggerModule } from 'nestjs-pino';
|
|
|
|
import { ApiExceptionFilter } from './common/api-exception.filter';
|
|
import { AppConfig } from './config/app-config.service';
|
|
import { ConfigModule } from './config/config.module';
|
|
import { HealthModule } from './health/health.module';
|
|
|
|
@Module({
|
|
imports: [
|
|
ConfigModule,
|
|
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 {}
|