import { plainToClass } from 'class-transformer'; import { IsEnum, IsIn, IsNotEmpty, IsNumber, IsString, Max, Min, validateSync } from 'class-validator'; import { BOOLEAN_STRING_VALUES } from '../consts/booleanStringValues'; import type { BooleanStringValue } from '../types/BooleanStringValue'; import { NodeEnv } from '../types/NodeEnv'; class EnvironmentVariables { @IsNotEmpty() @IsEnum(NodeEnv) NODE_ENV: NodeEnv; @IsNotEmpty() @IsNumber() @Min(1) @Max(65535) BACKEND_PORT: number; @IsNotEmpty() @IsString() POSTGRES_USER: string; @IsNotEmpty() @IsString() POSTGRES_PASSWORD: string; @IsNotEmpty() @IsString() POSTGRES_DB: string; @IsNotEmpty() @IsString() POSTGRES_HOST: string; @IsNotEmpty() @IsNumber() @Min(1) @Max(65535) POSTGRES_PORT: number; @IsNotEmpty() @IsIn(BOOLEAN_STRING_VALUES) POSTGRES_MIGRATIONS_RUN: BooleanStringValue; @IsNotEmpty() @IsString() CORS_ORIGINS: string; @IsNotEmpty() @IsIn(BOOLEAN_STRING_VALUES) ALTCHA_ENABLED: BooleanStringValue; @IsNotEmpty() @IsString() ALTCHA_HMAC_KEY: string; @IsNotEmpty() @IsNumber() @Min(1) @Max(1_000_000) ALTCHA_MAX_NUMBER: number; @IsNotEmpty() @IsNumber() @Min(60_000) @Max(3_600_000) ALTCHA_CHALLENGE_TTL_MS: number; @IsNotEmpty() @IsNumber() @Min(1000) @Max(3_600_000) THROTTLE_TTL_MS: number; @IsNotEmpty() @IsNumber() @Min(1) @Max(1_000_000) THROTTLE_LIMIT: number; @IsNotEmpty() @IsNumber() @Min(1000) @Max(3_600_000) THROTTLE_UPLOAD_TTL_MS: number; @IsNotEmpty() @IsNumber() @Min(1) @Max(10_000) THROTTLE_UPLOAD_LIMIT: number; @IsNotEmpty() @IsNumber() @Min(1) @Max(10_000_000) VALIDATION_UPLOAD_MAX_VIEWS_MAX: number; @IsNotEmpty() @IsNumber() @Min(1) @Max(50 * 1024 * 1024) // 50MB VALIDATION_UPLOAD_MAX_IMAGE_BYTES: number; @IsNotEmpty() @IsNumber() @Min(256 * 1024) // 256KiB @Max(16 * 1024 * 1024) // 16MB VALIDATION_UPLOAD_JSON_BODY_PADDING_BYTES: number; } export const validate = (config: Record) => { const validatedConfig = plainToClass(EnvironmentVariables, config, { enableImplicitConversion: true }); const errors = validateSync(validatedConfig, { skipMissingProperties: false }); if (errors.length > 0) { throw new Error(errors.toString()); } return validatedConfig; };