Перейти к содержимому

Конфиги и переменные окружения (libs/apis/configs)

libs/apis/configs — набор Nx-библиотек-конфигов поверх @nestjs/config. Каждый конфиг инкапсулирует одну группу env-переменных, валидирует их через Joi и предоставляет типобезопасный сервис-геттер. Разделены на:

  • shared/* — общие для нескольких приложений: app, redis, s3, smtp, rabbit.
  • auth-api/* — специфичные для аутентификации: jwt-customer, jwt-employee, jwt-admin.

Каждый конфиг состоит из 4 (иногда 5) файлов. Разберём на примере shared/app:

  1. app.env.ts — читает «сырые» переменные из process.env, приводит типы (например parseInt(APP_PORT)), задаёт дефолты и описывает TS-интерфейс:

    export const getAppEnvironment = (): AppEnvironmentVariables => {
    const { APP_ENV, APP_PORT } = process.env as Record<string, string>;
    return { APP_ENV, APP_PORT: parseInt(APP_PORT, 10) || 3000 };
    };
  2. app.config.ts — регистрирует namespaced-конфиг через registerAs('app', ...), раскладывая env в структуру:

    export const appConfig = registerAs('app', () => {
    const env = getAppEnvironment();
    return { env: env.APP_ENV, port: env.APP_PORT };
    });
  3. app-config.validation.ts — Joi-схема валидации значений process.env. .required() означает обязательность:

    export const validationSchema = Joi.object({
    APP_ENV: Joi.string().valid('development', 'production', 'stage'),
    APP_PORT: Joi.number(),
    });
  4. app-config.service.ts — инъектируемый сервис-обёртка над ConfigService с типизированными геттерами:

    @Injectable()
    export class AppConfigService {
    constructor(private configService: ConfigService<Record<string, unknown>, true>) {}
    get env(): string { return this.configService.get<string>('app.env'); }
    get port(): number { return this.configService.get<number>('app.port'); }
    }
  5. app-config.module.ts — модуль, подключающий namespaced-конфиг и схему валидации, экспортирующий сервис:

    @Module({
    imports: [ConfigModule.forRoot({ load: [appConfig], validationSchema })],
    providers: [ConfigService, AppConfigService],
    exports: [ConfigService, AppConfigService],
    })
    export class AppConfigModule {}

Остальные конфиги повторяют этот паттерн один-в-один (у jwt-admin есть дополнительный пустой jwt-admin.module.ts — заглушка). Потребители импортируют *ConfigModule и инжектят *ConfigService.

Столбец «Обязательна» отражает Joi-схему: Да — есть .required(); Нет — переменная в схеме без .required() (валидируется по типу, но не обязательна); Да (default N).required()/наличие с дефолтом. Дефолты в скобках берутся из *.env.ts (parseInt || N).

ПеременнаяКонфиг-модульТипОбязательнаНазначение
APP_ENVshared/app (AppConfigModule)string (development/production/stage)НетТекущее окружение; влияет на уровень логов Prisma
APP_PORTshared/appnumber (default 3000)НетHTTP-порт приложения
REDIS_HOSTshared/redis (RedisConfigModule)stringДаХост Redis
REDIS_PORTshared/redisnumber (default 6379)ДаПорт Redis
REDIS_PASSWORDshared/redisstring (allow '')ДаПароль Redis (может быть пустым)
S3_ENDPOINTshared/s3 (S3ConfigModule)stringДаEndpoint S3-совместимого хранилища
S3_REGIONshared/s3stringДаРегион S3
S3_ACCESS_KEY_IDshared/s3stringДаAccess key ID
S3_SECRET_ACCESS_KEYshared/s3stringДаSecret access key
S3_BUCKETshared/s3stringДаИмя бакета (аватары, портфолио)
SMTP_HOSTshared/smtp (SmtpConfigModule)stringДаХост SMTP-сервера
SMTP_PORTshared/smtpnumber (default 587)ДаПорт SMTP
SMTP_USERshared/smtpstringДаЛогин SMTP (маппится в username)
SMTP_PASSWORDshared/smtpstringДаПароль SMTP
SMTP_FROMshared/smtpstringДаАдрес отправителя (from по умолчанию)
RABBITMQ_HOSTshared/rabbit (RabbitConfigModule)stringДаХост RabbitMQ
RABBITMQ_PORTshared/rabbitnumber (default 5672)ДаПорт RabbitMQ
RABBITMQ_USERNAMEshared/rabbitstringДаЛогин RabbitMQ
RABBITMQ_PASSWORDshared/rabbitstring (allow '')ДаПароль RabbitMQ
RABBITMQ_PREFETCHshared/rabbitnumber (default 50)Да (default 50)Prefetch канала
RABBITMQ_REQUEST_QUEUEshared/rabbitstringДаОчередь запросов
RABBITMQ_REQUEST_EXCHANGEshared/rabbitstringДаExchange запросов
RABBITMQ_REQUEST_EXCHANGE_TYPEshared/rabbitstringДаТип exchange запросов
RABBITMQ_RESPONSES_QUEUEshared/rabbitstringДаОчередь ответов
RABBITMQ_RESPONSES_EXCHANGEshared/rabbitstringДаExchange ответов
RABBITMQ_RESPONSES_EXCHANGE_TYPEshared/rabbitstringДаТип exchange ответов
JWT_CUSTOMER_ACCESS_SECRET_KEYauth-api/jwt-customer (JwtCustomerConfigModule)stringНетСекрет access-токена клиента
JWT_CUSTOMER_ACCESS_EXPIRES_INauth-api/jwt-customernumber (default 3600)НетTTL access-токена клиента (сек)
JWT_CUSTOMER_REFRESH_SECRET_KEYauth-api/jwt-customerstringНетСекрет refresh-токена клиента
JWT_CUSTOMER_REFRESH_EXPIRES_INauth-api/jwt-customernumber (default 7200)НетTTL refresh-токена клиента (сек)
JWT_EMPLOYEE_ACCESS_SECRET_KEYauth-api/jwt-employee (JwtEmployeeConfigModule)stringНетСекрет access-токена сотрудника
JWT_EMPLOYEE_ACCESS_EXPIRES_INauth-api/jwt-employeenumber (default 3600)НетTTL access-токена сотрудника (сек)
JWT_EMPLOYEE_REFRESH_SECRET_KEYauth-api/jwt-employeestringНетСекрет refresh-токена сотрудника
JWT_EMPLOYEE_REFRESH_EXPIRES_INauth-api/jwt-employeenumber (default 7200)НетTTL refresh-токена сотрудника (сек)
JWT_ADMIN_ACCESS_SECRET_KEYauth-api/jwt-admin (JwtAdminConfigModule)stringДаСекрет access-токена админа
JWT_ADMIN_ACCESS_EXPIRES_INauth-api/jwt-adminnumber (default 3600)ДаTTL access-токена админа (сек)
JWT_ADMIN_REFRESH_SECRET_KEYauth-api/jwt-adminstringДаСекрет refresh-токена админа
JWT_ADMIN_REFRESH_EXPIRES_INauth-api/jwt-adminnumber (default 7200)ДаTTL refresh-токена админа (сек)
ADMIN_ALLOWED_DOMAINSauth-api/jwt-adminstring (CSV)ДаСписок разрешённых доменов админ-почты; парсится в string[] (split по ,, trim, lower-case)
  • jwt-customer / jwt-employee: секреты и TTL описаны в Joi без .required(), поэтому формально необязательны, но для реальной работы аутентификации секреты должны быть заданы. TTL имеют дефолты в *.env.ts (3600 / 7200).
  • jwt-admin — единственный jwt-конфиг со строгой валидацией (.required()) плюс дополнительный геттер allowedDomains: string[].
  • REDIS_PASSWORD и RABBITMQ_PASSWORD используют Joi.string().allow('').required() — переменная обязана присутствовать, но может быть пустой строкой.
  • Значения из parseInt(... ) || N в *.env.ts дают запасной дефолт даже если Joi пропускает пустое значение.