mancuoj

mancuoj

Better late than never.
github
twitter

使用 Zod 安全地读取你的环境变量

用 zod 来验证环境变量,可以做到两件事:

  1. 如果缺少任何必需的环境变量,就在启动时使 app 崩溃
  2. 为环境变量添加类型定义,以便我们可以在 IDE 中获得自动完成和类型检查

直接上代码:

const envSchema = z.object({
  SESSION_SECRET: z.string().min(1),
  DOMAIN_NAME: z.string().min(1),
})

declare global {
  namespace NodeJS {
    interface ProcessEnv extends TypeOf<typeof envSchema> {}
  }
}

envSchema.parse(process.env)

Remix 可以这样:

// env.server.ts
import { TypeOf, z } from 'zod'

const envSchema = z.object({
  SESSION_SECRET: z.string().min(1),
  DOMAIN_NAME: z.string().min(1),
})

declare global {
  namespace NodeJS {
    interface ProcessEnv extends TypeOf<typeof envSchema> {}
  }
}

try {
  envSchema.parse(process.env)
} catch (err) {
  if (err instanceof z.ZodError) {
    console.error(err.flatten())
    const { fieldErrors } = err.flatten()
    const errorMessage = Object.entries(fieldErrors)
      .map(([field, errors]) => (errors ? `${field}: ${errors.join(', ')}` : field))
      .join('\n  ')
    throw new Error(`Missing environment variables:\n  ${errorMessage}`)
  }
}

然后在 entry.server.ts 中导入:

import '~/env.server'

Bonus#

或者可以直接用 t3 env,原理都是一样的。

import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
 
export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    OPEN_AI_API_KEY: z.string().min(1),
  },
 
  /**
   * The prefix that client-side variables must have. This is enforced both at
   * a type-level and at runtime.
   */
  clientPrefix: "PUBLIC_",
 
  client: {
    PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
  },
 
  /**
   * What object holds the environment variables at runtime. This is usually
   * `process.env` or `import.meta.env`.
   */
  runtimeEnv: process.env,
 
  /**
   * By default, this library will feed the environment variables directly to
   * the Zod validator.
   *
   * This means that if you have an empty string for a value that is supposed
   * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
   * it as a type mismatch violation. Additionally, if you have an empty string
   * for a value that is supposed to be a string with a default value (e.g.
   * `DOMAIN=` in an ".env" file), the default value will never be applied.
   *
   * In order to solve these issues, we recommend that all new projects
   * explicitly specify this option as true.
   */
  emptyStringAsUndefined: true,
});
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。