ntro 0.3.4

Introspect configuration files and generate typescript type declarations or other useful typescript code.
Documentation
---
source: src/dotenv/zod.rs
expression: output
---

import z, { ZodTypeAny } from "zod";

const clientEnvSchemas = {
    NEXT_PUBLIC_ENVIRONMENT: z.enum(['qa','development','production']) /* from "src/dotenv/.env.test" on line 10 */,
}

const serverEnvSchemas = {
    ...clientEnvSchemas,
    KEY: z.string(),
    KEY_Value: z.coerce.number() /* from "src/dotenv/.env.test2" on line 4 */,
    NAME: z.enum(['val','value']) /* from "src/dotenv/.env.test2" on line 10 */,
    NAME2: z.enum(['a','b']) /* from "src/dotenv/.env.test" on line 6 */,
    NAME5: z.string(),
    keys: z.string(),
    keys2: z.string() /* from "src/dotenv/.env.test" on line 18 */,
    keys2Da: z.enum(['city','townhall']) /* from "src/dotenv/.env.test2" on line 7 */,
}


export const clientEnv: z.infer<z.ZodObject<typeof clientEnvSchemas>> =
  new Proxy({} as any, {
    get(_, prop: string) {
      return lookupEnv(prop, clientEnvSchemas, () => {
        throw new Error(
          `${prop} is not defined for client side environment variables.`
        );
      });
    },
  });

export const env: z.infer<z.ZodObject<typeof serverEnvSchemas>> = new Proxy(
  {} as any,
  {
    get(_, prop: string) {
      if (prop.startsWith("NEXT_PUBLIC_")) {
        return Reflect.get(clientEnv, prop);
      }
      return lookupEnv(prop, serverEnvSchemas, () => {
        throw new Error(
          `${prop} is not defined for server side environment variables.`
        );
      });
    },
  }
);

const cache: Record<string, unknown> = {};

function lookupEnv<T extends Record<string, ZodTypeAny>>(
  prop: string,
  parsers: T,
  onNotFound: () => never
) {
  if (prop in cache) {
    return cache[prop];
  }

  try {
    if (prop in parsers) {
      const parsed = parsers[prop as keyof typeof parsers].parse(
        processEnv[prop as keyof typeof processEnv],
        { path: [prop] }
      );

      cache[prop] = parsed;

      return parsed;
    }
    onNotFound();
  } catch (e) {
    throw new BadEnvError(`failed to read ${prop} from proccess.env`, e);
  }
}

class BadEnvError extends Error {
  constructor(public message: string, public cause: unknown) {
    super(message);
    if (cause instanceof Error) {
      this.message = [message, cause].join("\n ↳ ");
    }
  }
}

const processEnv = {
   KEY: process.env.KEY,
   KEY_Value: process.env.KEY_Value,
   NAME: process.env.NAME,
   NAME2: process.env.NAME2,
   NAME5: process.env.NAME5,
   NEXT_PUBLIC_ENVIRONMENT: process.env.NEXT_PUBLIC_ENVIRONMENT,
   keys: process.env.keys,
   keys2: process.env.keys2,
   keys2Da: process.env.keys2Da,
}