UNPKG

validate-env-vars

Version:

A lightweight utility to check the presence and validity of environment variables, as specified by a Zod schema

2 lines (1 loc) 3.99 kB
var R="\x1B[31m",O="\x1B[33m",g="\x1B[32m",c="\x1B[0m",_=`${R}\u2715${c}`,h=`${g}\u2714${c}`,S=`${O}\u26A0${c}`,w=`${O}\u2192${c}`;import*as p from"zod/v4/core";function M(e){let t=e.meta?.();if(!t||typeof t!="object")return{};let o=t,n={};return typeof o.title=="string"&&(n.title=o.title),typeof o.description=="string"&&(n.description=o.description),Array.isArray(o.examples)&&o.examples.every(r=>typeof r=="string")&&(n.examples=o.examples),n}function V(e){let t=Object.entries(e);t.length!==0&&t.forEach(([o,n])=>{let r=typeof n=="string"?n:JSON.stringify(n),i=` ${w} ${O}${o}${c}: ${r}`.trimEnd();console.log(i)})}function A(e){if(typeof e!="object"||e===null)return!1;let t=e._zod?.traits;return t instanceof Set&&t.has("ZodOptional")}function B(e,t,o,n){let r=t._zod.def.shape,i={};for(let[a,s]of Object.entries(r))i[a]={optional:A(s),error:null,meta:M(s),data:a in o?o[a]:void 0};if(e.success){let{data:a}=e;for(let[s,l]of Object.entries(a))i[s].data=l}else for(let a of e.error.issues){let s=a.path[0],l=a.message;i[s]={...i[s],data:null,error:l}}let d=0;return Object.entries(i).forEach(([a,s])=>{if(s.error===null&&s.data!==void 0&&s.data!==""){let l=n?` ${g}'${s.data}'${c}`:"",f=`${h} ${a}${l}`.trim();console.log(f)}else if(s.error===null){let l=s.data===void 0?"undefined":`'${s.data}'`,f=n?`${O}${l}${c}`:"",u=`${S} ${a} ${f}`.trim();console.log(u),V(s.meta)}else{let l=`${_} ${a}: ${R}${s.error||""}${c}`.trim();console.error(l),V(s.meta),d++}}),d}var z=B;var F=new Set(["string","enum","literal"]);function y(e){let t=e._zod.def.type;if(F.has(t))return!0;if(t==="union"&&e instanceof p.$ZodUnion)return e._zod.def.options.every(r=>y(r));if(t==="optional"&&e instanceof p.$ZodOptional){let n=e._zod.def.innerType;return y(n)}return!1}function Z(e,t){if(!("_zod"in t&&"traits"in t._zod&&t._zod.traits instanceof Set))throw new Error(`The provided field must be a ZodType from Zod v4. Received: ${typeof t}`);if(!y(t)){let n=t._zod.def.type;throw new Error(`Field "${e}" has invalid type "${n}". Environment variables must be string-based types (string, enum, literal, etc.)`)}}function L(e){if(!("_zod"in e&&"traits"in e._zod&&e._zod.traits instanceof Set&&(e._zod.traits.has("ZodObject")||e._zod.traits.has("ZodMiniObject"))))throw new Error(`The provided schema must be a ZodObject from Zod v4. Received: ${typeof e}`);let o=e._zod.def.shape;Object.entries(o).forEach(([n,r])=>{Z(n,r)})}function T(e){let{schema:t,vars:o,logVars:n}=e,r=p.safeParse(t,o),i=z(r,t,o,n);if(!r.success){let d=i===1?"":"s";throw new Error(`${i.toString()} missing or invalid environment variable${d}`)}console.log(`${g}All required environment variables are valid${c}`)}import{loadEnvFile as k}from"process";var I=/(?<!\\)(?:\${([^{}]+)}|\$([A-Za-z_][A-Za-z0-9_]*))/g,Y=/(:?[+-])/;function P(e){return e.replace(/\\\$/g,"$")}function K(e,t){let o=new RegExp(I.source,"g"),n=e,r,i=new Set,d=10,a=0;for(;(r=o.exec(n))!==null;){if(a++>d)throw new Error("Possible circular reference detected during environment variable expansion");i.add(n);let[s,l,f]=r,u=l||f,m=u.match(Y)?.[0]??null,$=m?u.split(m):[u],x=$[0],b=$.slice(1).join(m??""),E;if(m===":+"||m==="+")E=t[x]?b:"";else{let v=t[x];if(v!==void 0&&v!==""){if(i.has(v))throw new Error("Possible self-reference detected during environment variable expansion");E=v}else E=b}if(n=n.replace(s,E),o.lastIndex=0,n===t[x])break}return n}function N(e){let t={};for(let[o,n]of Object.entries(e))n!==void 0&&(t[o]=n);for(let o of Object.keys(e)){let n=e[o];if(n===void 0)continue;let r=K(n,t),i=P(r);t[o]=i}return t}function j(e){let{schema:t,vars:o}=e,n=Object.keys(t._zod.def.shape);return Object.fromEntries(Object.entries(o).filter(([i])=>n.includes(i)))}function C(e){return e&&k(e),N(process.env)}function W({schema:e,envPath:t,exitOnError:o=!1,logVars:n=!0}){try{L(e);let r=C(t),i=j({schema:e,vars:r});T({schema:e,vars:i,logVars:n})}catch(r){if(o)console.error(`${R}${r.message}${c}`),process.exit(1);else throw r}}var re=W;export{re as default};