import { createEnv } from '@t3-oss/env-nextjs' import * as z from 'zod' /** * z.string() // 必须是字符串 z.string().min(1) // 字符串且不能是空字符串(最常用的"必填"写法) z.string().url() // 必须是合法 URL 格式(http://xxx 或 https://xxx) z.string().length(3) // 字符串长度必须恰好是 3(比如货币代码 USD) z.enum(['a', 'b']) // 值必须是给定的几个字符串之一,多了写不了就用这个 z.string().startsWith('pk_') // 必须以某个前缀开头 .default('xxx') // 如果没配置,给个默认值,不会校验失败 .optional() // 允许是 undefined(不常用在这里,因为你都要求必填) */ export const env = createEnv({ /** * 服务端变量:只能在服务端代码里访问(API Route / Server Component / Server Action) * 客户端组件里引用会直接报错,防止密钥泄漏 */ server: { // 业务环境标识,限定只能是这几个值之一 APP_ENV: z.enum(['development', 'test', 'production']), // NextAuth 配置 NEXTAUTH_URL: z.url(), // NextAuth 官方建议至少 32 位随机字符串,这里加个长度校验,防止手滑写太短 NEXTAUTH_SECRET: z.string().min(32, 'NEXTAUTH_SECRET 长度至少 32 位,建议用 openssl rand -base64 32 生成'), // PayPal PAYPAL_SANDBOX_CLIENT_ID: z.string().min(1), PAYPAL_PRODUCTION_CLIENT_ID: z.string().min(1), // 业务配置 COMPANY_NAME: z.string().min(1), STORE_NAME: z.string().min(1), DEFAULT_CURRENCY: z.string().length(3), // 货币代码固定 3 位,比如 USD、CNY DEFAULT_LOCAL: z.string().min(2), // 语言代码,比如 en、zh-CN DEFAULT_CHANNEL: z.string().min(1), }, /** * 客户端变量:必须以 NEXT_PUBLIC_ 开头,会被打包进浏览器 bundle,不要放密钥 */ client: { NEXT_PUBLIC_APP_ENV: z.enum(['development', 'test', 'production']), NEXT_PUBLIC_SITE_URL: z.url(), NEXT_PUBLIC_BAGISTO_ENDPOINT: z.url(), // storefront key 有固定前缀,顺手校验一下,配错了能第一时间发现 NEXT_PUBLIC_BAGISTO_STOREFRONT_KEY: z.string().startsWith('pk_storefront_'), }, /** * 只需要列出 client 变量即可,Next.js >= 13.4.4 都用这个写法 */ experimental__runtimeEnv: { NEXT_PUBLIC_APP_ENV: process.env.NEXT_PUBLIC_APP_ENV, NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_BAGISTO_ENDPOINT: process.env.NEXT_PUBLIC_BAGISTO_ENDPOINT, NEXT_PUBLIC_BAGISTO_STOREFRONT_KEY: process.env.NEXT_PUBLIC_BAGISTO_STOREFRONT_KEY, }, /** * docker build 或 CI 阶段如果没有真实环境变量,可以临时跳过校验 * SKIP_ENV_VALIDATION 变量需要在docker的配置文件中注入 */ skipValidation: !!process.env.SKIP_ENV_VALIDATION, /** * .env 里如果某个变量写成空字符串(比如 XXX=),当作没配置处理,而不是校验通过一个空串 */ emptyStringAsUndefined: true, })