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,
});
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。