Files
gold_land_server/src/config/env.validation.ts
T

61 lines
1.6 KiB
TypeScript
Raw Normal View History

import { plainToInstance } from 'class-transformer'
import { IsIn, IsInt, IsOptional, IsString, Min, validateSync } from 'class-validator'
export class EnvironmentVariables {
@IsIn(['development', 'production', 'test'])
NODE_ENV!: 'development' | 'production' | 'test'
@IsInt()
@Min(1)
PORT!: number
@IsString()
HOST!: string
@IsString()
CORS_ORIGIN!: string
@IsOptional()
@IsString()
DB_PATH?: string
@IsOptional()
@IsString()
JWT_SECRET?: string
}
export function validateEnv(config: Record<string, unknown>): EnvironmentVariables {
const nodeEnv = (config.NODE_ENV as string | undefined) ?? 'development'
const jwtSecret = config.JWT_SECRET as string | undefined
if (nodeEnv === 'production' && (!jwtSecret || jwtSecret.trim().length === 0)) {
throw new Error('JWT_SECRET is required when NODE_ENV=production')
}
if (nodeEnv !== 'production' && !jwtSecret) {
console.warn(
'[config] JWT_SECRET is not set — using development fallback. Do not use in production.',
)
}
const normalized = {
NODE_ENV: nodeEnv,
PORT: Number(config.PORT ?? 3001),
HOST: (config.HOST as string | undefined) ?? '0.0.0.0',
CORS_ORIGIN: (config.CORS_ORIGIN as string | undefined) ?? 'http://localhost:5173',
DB_PATH: config.DB_PATH as string | undefined,
JWT_SECRET: jwtSecret ?? 'gold-land-dev-secret-change-in-production',
}
const validated = plainToInstance(EnvironmentVariables, normalized, {
enableImplicitConversion: true,
})
const errors = validateSync(validated, { skipMissingProperties: false })
if (errors.length > 0) {
throw new Error(errors.toString())
}
return validated
}