[{"data":1,"prerenderedAt":169},["ShallowReactive",2],{"content:\u002Fposts\u002F2025\u002Fsecurely-share-environment-variables":3,"surround:\u002Fposts\u002F2025\u002Fsecurely-share-environment-variables":158},{"id":4,"title":5,"body":6,"canonical":130,"categories":131,"date":133,"description":134,"draft":135,"extension":136,"image":137,"meta":138,"navigation":139,"path":140,"permalink":130,"readingTime":141,"recommend":146,"references":147,"seo":151,"sitemap":152,"stem":153,"tags":154,"type":130,"updated":133,"__hash__":157},"content\u002Fposts\u002F2025\u002Fsecurely-share-environment-variables.md","使用 zod 对.env 文件约束",{"type":7,"value":8,"toc":117},"minimark",[9,14,25,32,37,44,53,56,63,70,73,76,82,85,109,112],[10,11,13],"h2",{"id":12},"为你的项目安装-zod","为你的项目安装 zod",[15,16,22],"pre",{"className":17,"code":19,"language":20,"meta":21},[18],"language-bash","pnpm i zod\n","bash","",[23,24,19],"code",{"__ignoreMap":21},[10,26,28,29],{"id":27},"创建-envts","创建 ",[23,30,31],{"code":31},"env.ts",[33,34,36],"h3",{"id":35},"vue-项目中使用","vue 项目中使用",[38,39,40],"alert",{},[41,42,43],"p",{},"我这里的 toast 是使用 shadcn-vue 组件库的提示插件，如果您的项目中使用其他的组件库，可以替换为您使用的组件库的提示插件。它只是为了全局提醒您的 env 变量某些部分与规定的类型不一致。",[15,45,51],{"className":46,"code":48,"filename":49,"language":50,"meta":21},[47],"language-ts","import { h } from 'vue'\nimport { z } from 'zod'\n\nimport { toast } from '@\u002Fcomponents\u002Fui\u002Ftoast'\n\n\u002F**\n * Load .env file and validate it against the schema\n * Has this file, it will be loaded automatically by vite and we will be have environment variables available type\n * If EnvSchema Object has Key but not in .env file, it will be have a error in page\n *\u002F\n\nconst EnvSchema = z.object({\n    \u002F\u002F Add your environment variables here, for example:\n    VITE_API_BASE_URL: z.string().url(),\n})\n\nexport type env = z.infer\u003Ctypeof EnvSchema>\n\nconst { data: env, error } = EnvSchema.safeParse(import.meta.env)\n\nif (error) {\n    console.error('❌ Invalid env')\n    console.error(error.flatten().fieldErrors)\n    toast({\n        title: `Env error: you should check your .env file`,\n        variant: 'destructive',\n        description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(error, null, 2))),\n    })\n}\n\nexport default env!\n","utils\u002Fenv.ts","ts",[23,52,48],{"__ignoreMap":21},[41,54,55],{},"在 vue 入口文件引入它",[15,57,61],{"className":58,"code":59,"filename":60,"language":50,"meta":21},[47],"import '@\u002Futils\u002Fenv'\n","main.ts",[23,62,59],{"__ignoreMap":21},[41,64,65,66,69],{},"有了这个文件后，如果您的环境变量中没有 ",[23,67,68],{"code":68},"VITE_API_BASE_URL","，就会全局提示一个错误，提醒您配置对应的环境变量。",[33,71,72],{"id":72},"node项目中使用",[41,74,75],{},"当然，它也可以运行至node 项目中，且可以在 env 变量与规定不一致时，退出程序",[15,77,80],{"className":78,"code":79,"filename":31,"language":50,"meta":21},[47],"import { config } from \"dotenv\";\nimport { expand } from \"dotenv-expand\";\nimport { z } from \"zod\";\n\nexpand(config());\n\nconst EnvSchema = z.object({\n    NODE_ENV: z.string().default(\"development\"),\n    LOG_LEVEL: z.enum([\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"silent\"]),\n    PORT: z.coerce.number().default(9999),\n\n    \u002F\u002F database\n    DB_HOST: z.string(),\n    DB_USER: z.string(),\n    DB_PASSWORD: z.string(),\n    DB_NAME: z.string(),\n    DB_PORT: z.coerce.number(),\n    DATABASE_URL: z.string(),\n\n    \u002F\u002F jwt\n    ACCESS_TOKEN_SECRET: z.string(),\n    REFRESH_TOKEN_SECRET: z.string(),\n    COOKIE_SECRET: z.string(),\n});\n\nexport type env = z.infer\u003Ctypeof EnvSchema>;\n\nconst { data: env, error } = EnvSchema.safeParse(process.env);\nif (error) {\n    console.error(\"❌ Invalid env\");\n    console.error(error.flatten().fieldErrors);\n    process.exit(1);\n}\n\nexport default env!;\n",[23,81,79],{"__ignoreMap":21},[10,83,84],{"id":84},"使用技巧",[38,86,87],{},[88,89,90,102],"ul",{},[91,92,93,94,97,98,101],"li",{},"我们可以使用 ",[23,95,96],{"code":96},".default()"," 来给它一个默认值，如 ",[23,99,100],{"code":100},"NODE_ENV: z.string().default(\"development\"),"," 就是在 NODE_ENV 没有设置时设置为 development",[91,103,104,105,108],{},"在 node 端，使用 ",[23,106,107],{"code":107},"process.exit(1)"," 会在必填的环境变量没有时退出",[10,110,111],{"id":111},"视频版本",[113,114],"video-embed",{"id":115,"type":116},"BV1bckuYpE37","bilibili",{"title":21,"searchDepth":118,"depth":118,"links":119},4,[120,122,128,129],{"id":12,"depth":121,"text":13},2,{"id":27,"depth":121,"text":123,"children":124},"创建 env.ts",[125,127],{"id":35,"depth":126,"text":36},3,{"id":72,"depth":126,"text":72},{"id":84,"depth":121,"text":84},{"id":111,"depth":121,"text":111},null,[132],"代码","2025-01-15 14:52:04","使你的环境变量拥有类型,这个是从 Syntax 播客的 CJ 那里学过来的",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002Fsecurely-share-environment-variables.png",{},true,"\u002Fposts\u002F2025\u002Fsecurely-share-environment-variables",{"text":142,"minutes":143,"time":144,"words":145},"3 min read",2.305,138300,461,1,[148],{"title":149,"link":150},"hono-open-api-starter","https:\u002F\u002Fgithub.com\u002Fw3cj\u002Fhono-open-api-starter",{"title":5,"description":134},{"loc":140},"posts\u002F2025\u002Fsecurely-share-environment-variables",[155,156],"zod","env","jCC3azbKpXxWmYPgWAPimxRdvvkh5nsJJ7ee1thc0po",[159,164],{"title":160,"path":161,"stem":162,"date":163,"type":130,"children":-1},"从本地到生产：使用 Docker 部署 Nuxt","\u002Fposts\u002F2025\u002Ffrom-local-to-production-deploy-nuxt-with-docker","posts\u002F2025\u002Ffrom-local-to-production-deploy-nuxt-with-docker","2025-01-15 14:16:16",{"title":165,"path":166,"stem":167,"date":168,"type":130,"children":-1},"Git 提交规范及其在项目里的使用","\u002Fposts\u002F2025\u002Fgit-angular-push-rules","posts\u002F2025\u002Fgit-angular-push-rules","2025-01-16 07:31:53",1789642585423]