Skip to content

Commit 1ba8134

Browse files
committed
Validate required environment variables at startup
1 parent e077c52 commit 1ba8134

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { APP_GUARD } from '@nestjs/core';
33
import { AppController } from './app.controller';
44
import { ConfigModule } from '@nestjs/config';
55
import { PrismaModule } from './prisma/prisma.module';
6+
import { validateEnvironment } from './common/config/env.validation';
67
import { AppService } from './app.service';
78
import { UsersModule } from './users/users.module';
89
import { IdempotentUserModule } from './users/idempotent-user.module';
@@ -29,6 +30,7 @@ import { HealthModule } from './health/health.module';
2930
ConfigModule.forRoot({
3031
isGlobal: true,
3132
envFilePath: '.env',
33+
validate: validateEnvironment,
3234
}),
3335
PrismaModule,
3436
AuthModule,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { plainToInstance } from 'class-transformer';
2+
import {
3+
IsInt,
4+
IsNotEmpty,
5+
IsOptional,
6+
IsString,
7+
IsUrl,
8+
Min,
9+
MinLength,
10+
validateSync,
11+
} from 'class-validator';
12+
13+
export class EnvironmentVariables {
14+
@IsString()
15+
@IsNotEmpty()
16+
DATABASE_URL!: string;
17+
18+
@IsString()
19+
@IsNotEmpty()
20+
@MinLength(32)
21+
WALLET_ENCRYPTION_KEY!: string;
22+
23+
@IsString()
24+
@IsNotEmpty()
25+
@IsUrl({ require_protocol: true })
26+
STELLAR_HORIZON_URL!: string;
27+
28+
@IsOptional()
29+
@IsInt()
30+
@Min(1)
31+
PORT?: number;
32+
}
33+
34+
export function validateEnvironment(config: Record<string, unknown>) {
35+
const validatedConfig = plainToInstance(EnvironmentVariables, config, {
36+
enableImplicitConversion: true,
37+
});
38+
39+
const errors = validateSync(validatedConfig, {
40+
skipMissingProperties: false,
41+
});
42+
43+
if (errors.length > 0) {
44+
const message = errors
45+
.map((error) => {
46+
const constraints = error.constraints
47+
? Object.values(error.constraints).join(', ')
48+
: 'invalid value';
49+
return `${error.property}: ${constraints}`;
50+
})
51+
.join('; ');
52+
53+
throw new Error(`Invalid environment configuration: ${message}`);
54+
}
55+
56+
return validatedConfig;
57+
}

0 commit comments

Comments
 (0)