外观
环境变量校验
基于 Zod 的环境变量验证工具,在应用启动时校验 process.env,确保配置正确。
为什么需要环境变量校验?
- 快速失败:启动时就发现配置错误,而非运行时某个请求突然报错
- 类型安全:校验后的环境变量有完整的 TypeScript 类型
- 自动转换:字符串自动转为 number / boolean
基础用法
typescript
// config/env.ts
import { z } from 'zod'
import { validateEnv, zPort, zBoolEnv } from '@maxtan/nest-core'
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: zPort().default(3000),
DATABASE_URL: z.string().url(),
REDIS_HOST: z.string().default('localhost'),
REDIS_PORT: zPort().default(6379),
JWT_SECRET: z.string().min(16, 'JWT_SECRET 至少 16 位'),
ENABLE_SWAGGER: zBoolEnv().default(false),
})
export const env = validateEnv(envSchema)typescript
// main.ts
import { env } from './config/env'
async function bootstrap() {
createLogger({ useConsole: env.NODE_ENV === 'development' })
const app = await NestFactory.create(AppModule)
await app.listen(env.PORT) // number 类型,无需 parseInt
}API
validateEnv(schema, options?)
| 参数 | 类型 | 说明 |
|---|---|---|
schema | ZodType | Zod schema,定义环境变量结构 |
options.envSource | Record | 环境变量来源,默认 process.env |
options.onError | 'throw' | 'log' | 验证失败行为,默认 'throw' |
错误输出格式
验证失败时抛出 EnvValidationError,错误信息清晰可读:
EnvValidationError: 环境变量验证失败:
- DATABASE_URL: Required
- JWT_SECRET: JWT_SECRET 至少 16 位
- REDIS_PORT: Expected number, received nan内置预处理器
zPort()
端口号预处理器,自动转换字符串 → 数字,范围 1-65535。
typescript
const schema = z.object({
PORT: zPort().default(3000),
REDIS_PORT: zPort().default(6379),
})zBoolEnv()
布尔值环境变量预处理器。
| 输入值 | 结果 |
|---|---|
'true' / '1' / 'yes' | true |
'false' / '0' / 'no' / '' | false |
typescript
const schema = z.object({
ENABLE_SWAGGER: zBoolEnv().default(false),
DEBUG: zBoolEnv().default(false),
})zEnvStr()
必填字符串,自动 trim + 空字符串视为 undefined。
typescript
const schema = z.object({
DATABASE_URL: zEnvStr(),
JWT_SECRET: zEnvStr().pipe(z.string().min(16)),
})zEnvNum(toInt?)
数字环境变量预处理器。
typescript
const schema = z.object({
MAX_CONNECTIONS: zEnvNum(true).default(10), // 整数
RATE_LIMIT: zEnvNum().default(100.5), // 浮点数
})进阶用法
条件必填
typescript
const schema = z.object({
NODE_ENV: z.enum(['development', 'production']).default('development'),
SENTRY_DSN: z.string().optional(),
}).refine(
(env) => env.NODE_ENV !== 'production' || !!env.SENTRY_DSN,
{ message: '生产环境必须配置 SENTRY_DSN', path: ['SENTRY_DSN'] }
)仅打印错误不退出
typescript
const env = validateEnv(schema, { onError: 'log' })
// 验证失败时 console.error 打印错误,返回 null自定义来源
typescript
// 测试时传入自定义环境变量
const env = validateEnv(schema, {
envSource: {
PORT: '4000',
DATABASE_URL: 'mysql://test@localhost/test',
JWT_SECRET: 'test-secret-key-1234567',
}
})最佳实践
- 集中定义:将环境变量 Schema 放在
config/env.ts统一管理 - 服务启动最前面校验:在
main.ts的import阶段就完成校验,确保快速失败 - 严格模式:生产环境使用默认
onError: 'throw',绝不允许带着错误配置启动 - 类型安全:将
validateEnv()返回值导出为常量,全项目共享类型推导 - 条件必填:生产环境特有的配置(如 SENTRY_DSN)用
.refine()校验
typescript
// config/env.ts — 推荐的统一配置文件
import { z } from 'zod'
import { validateEnv, zPort, zBoolEnv, zEnvStr } from '@maxtan/nest-core'
export const env = validateEnv(
z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: zPort().default(3000),
DATABASE_URL: zEnvStr(),
REDIS_HOST: z.string().default('localhost'),
REDIS_PORT: zPort().default(6379),
JWT_SECRET: zEnvStr().pipe(z.string().min(16)),
ENABLE_SWAGGER: zBoolEnv().default(false),
})
)相关文档
- 快速开始 — main.ts 应用启动
- 授权模块 — JWT Secret 配置
- 缓存模块 — Redis 连接配置
- 验证管道 (Zod) — Zod 预处理器 & Schema 组合器