Главная / Статьи

Проверяйте переменные окружения Node.js с помощью Zod и TypeScript

Прекратите использовать process.env во всем коде Node.js. Один файл env.ts, проверенный с помощью Zod, выявляет отсутствующие секреты при запуске и предоставляет приложению настроки в формате TypeScript с типизацией.

Издатель: REACTAPP.TOP3 мин чтения663 слов

Источники: https://medium.com/@vetriselvan_11/validating-environment-variables-in-node-js-using-zod-typescript-guide-16f4b6bacaf4

Представьте себе сценарий развертывания в пятницу днем. Компиляция проходит успешно, сервер запускается, и все уходят домой. Через час пользователи сообщают, что вход в систему не работает. Оказывается, никто не установил значение JWT_SECRET в производственной среде. Приложение запускалось нормально, но начало выдавать ошибки, когда первый запрос попал на участок кода, требующий отсутствующего значения.

Частое использование process.env по всему кодовому базису повышает вероятность подобных инцидентов. Далее показано, как заменить эту практику на модуль конфигурации с проверкой и типизацией с использованием Zod и TypeScript.

Традиционный подход

Большинство кодов на Node.js берут конфигурацию прямо там, где она нужна: порт — в одном файле, строка подключения к базе данных — в другом.

// Some random controller file
const port = process.env.PORT || 3000;
mongoose.connect(process.env.MONGO_URI);

Это удобно, но у этого подхода есть три серьезных проблемы.

  1. Отсутствие безопасности типов. В TypeScript process.env.PORT имеет тип string | undefined. Если требуется число, каждое место вызова должно самостоятельно выполнять его парсинг.
  2. Незаметные сбои. При отсутствии MONGO_URI процесс не завершается при запуске. Он падает только тогда, когда наконец выполняется соответствующая строка кода, возможно, спустя несколько часов после успешной развертки.
  3. Отсутствие единого источника информации. Новичок не имеет списка переменных, необходимых приложению. Единственный вариант — искать во всем репозитории элементы process.env.

Один файл-контроллер

Решение заключается в том, чтобы прекратить изменять значение process.env в бизнес-логике. Один модуль, назовем его env.ts, считывает параметры окружения один раз при запуске, проверяет их и экспортирует объект с строгой типизацией. Все остальные модули импортируют этот объект.

Валидацию выполняет Zod — библиотека для проверки схем, ориентированная на TypeScript.

Установите её

npm install zod

Напишите схему

Разместите модуль в файле src/config/env.ts и точно опишите, каким должно быть окружение.

import dotenv from 'dotenv';
import { z } from 'zod';

// Load variables from .env file (if in development)
dotenv.config();

// 1. Define the schema
const envSchema = z.object({
  PORT: z.string().transform(Number).default('3000'),
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
  MONGO_URI: z.string(),
  JWT_SECRET: z.string(),
  JWT_EXPIRES_IN: z.string().default('1d'),
});

// 2. Parse the environment against the schema
const _env = envSchema.safeParse(process.env);

// 3. Fail fast if it's invalid
if (!_env.success) {
  console.error('Invalid environment variables:', _env.error.format());
  process.exit(1); // Crash the app immediately!
}

// 4. Export the typed, validated object
export const env = _env.data;

Что делает модуль

  • Он определяет требования. Переменная MONGO_URI является обязательной и должна иметь тип строка. Переменная PORT также передаётся в виде строки, после чего функция .transform(Number) преобразует её в число по умолчанию 3000. Переменная NODE_ENV должна иметь одно из трёх разрешённых значений.
  • Он мгновенно выявляет ошибки. Функция safeParse выполняется сразу при импорте файла, поэтому её необходимо разместить в самом начале файла-точки входа, будь то app.ts или server.ts. Если отсутствует какая-либо обязательная переменная или она имеет неверный формат, функция сообщает об ошибке, выводит подробное описание проблемы, а затем с помощью process.exit(1) прерывает работу процесса до того, как он начнёт обрабатывать запросы.
  • Он экспортирует объект с указанными типами. При успешной обработке преобразованные данные содержат типы, определённые библиотекой Zod, так что env.PORT уже является числом.

С этого момента любой файл может импортировать env и использовать его.

Что вы получаете

  • Автодополнение. При вводе env. в редакторе отображается список всех доступных переменных.
  • Отсутствие разрозненных решений на случай сбоев. Формулы || "default_value" исчезают из контроллеров, поскольку значения по умолчанию хранятся в схеме.
  • Встроенная документация. Схема представляет собой точный список того, что необходимо приложению для работы, что также помогает новичкам понять, что должно находиться в файле .env.

Отсутствие необходимой конфиденциальной информации теперь препятствует развертыванию в течение нескольких секунд при запуске с четким сообщением, вместо того чтобы проблема проявилась в виде недовольного пользователя спустя час.