Last active
April 23, 2025 23:36
-
-
Save jakeisnt/887b00674bc2e09fc24e97f330d9418c to your computer and use it in GitHub Desktop.
Revisions
-
jakeisnt revised this gist
Apr 23, 2025 . 1 changed file with 37 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,40 @@ import { z } from "zod"; // System for creating dynamically accessible environment variables // from a schema. // Schema for the environment variables. // `type` specifies the type of the environment variable. // `fallback` is the fallback value if the environment variable is not set. type EnvSchema<T extends string> = Record< T, { type: z.ZodType; } >; // Type for the environment variables. // We use zod metaprogramming to infer the type of the environment variables // based on the type specified in the Zod schema. type EnvType<T extends EnvSchema<string>> = { [K in keyof T]: T[K]["type"] extends z.ZodType ? z.infer<T[K]["type"]> : never; }; /** * Create an environment object from a schema. * @param schema - The schema to create the environment object from. * @returns The environment object. * * @example * const env = createEnv({ * PORT: { type: z.coerce.number().int().positive().default(5435) }, * DUMPS_DIR: { type: z.string().default(path.join(process.env.HOME || '', 'improvin/dumps')) }, * }); * * env.PORT; // 5435 * env.DUMPS_DIR; // /Users/jake/Documents/improvin/dumps */ const createEnv = <T extends EnvSchema<string>>(schema: T): EnvType<T> => { const env = { -
jakeisnt revised this gist
Apr 23, 2025 . 1 changed file with 8 additions and 53 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,41 +1,3 @@ */ const createEnv = <T extends EnvSchema<string>>(schema: T): EnvType<T> => { const env = { @@ -44,34 +6,27 @@ const createEnv = <T extends EnvSchema<string>>(schema: T): EnvType<T> => { for (const [key, config] of Object.entries(schema) as [ keyof T, T[keyof T] ][]) { Object.defineProperty(env, key, { get() { if (this._cache[key]) { return this._cache[key]; } const rawValue = process.env[String(key)]; const parsedValue = config.type.safeParse(rawValue); if (!parsedValue.success) { console.warn( `Invalid or missing value for ${key.toString()}:`, parsedValue.error ); } this._cache[key] = parsedValue.success ? parsedValue.data : config.type.parse(undefined); return this._cache[key]; }, }); -
jakeisnt renamed this gist
Nov 21, 2024 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
jakeisnt created this gist
Nov 21, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,83 @@ import { z } from 'zod'; // System for creating dynamically accessible environment variables // from a schema. // Schema for the environment variables. // `type` specifies the type of the environment variable. // `fallback` is the fallback value if the environment variable is not set. type EnvSchema<T extends string> = Record< T, { type: z.ZodType; fallback: z.infer<z.ZodType>; } >; // Type for the environment variables. // We use zod metaprogramming to infer the type of the environment variables // based on the type specified in the Zod schema. type EnvType<T extends EnvSchema<string>> = { [K in keyof T]: T[K]['type'] extends z.ZodType ? z.infer<T[K]['type']> : never; }; /** * Create an environment object from a schema. * @param schema - The schema to create the environment object from. * @returns The environment object. * * @example * const env = createEnv({ * PORT: { type: z.coerce.number().int().positive(), fallback: 5435 }, * DUMPS_DIR: { type: z.string(), fallback: path.join(process.env.HOME || '', 'improvin/dumps') }, * }); * * env.PORT; // 5435 * env.DUMPS_DIR; // /Users/jake/Documents/improvin/dumps */ const createEnv = <T extends EnvSchema<string>>(schema: T): EnvType<T> => { const env = { _cache: {} as EnvType<T>, }; for (const [key, config] of Object.entries(schema) as [ keyof T, T[keyof T], ][]) { Object.defineProperty(env, key, { get() { if (this._cache[key]) { return this._cache[key]; } const rawValue = process.env[String(key)] || (() => { console.warn( `${String(key)} not provided, defaulting to ${config.fallback}`, ); return config.fallback.toString(); })(); const parsedValue = config.type.safeParse(rawValue); if (!parsedValue.success) { console.error( `Invalid value for ${key.toString()}:`, parsedValue.error, ); return config.fallback; } this._cache[key] = parsedValue.data; return this._cache[key]; }, }); } return env as EnvType<T>; }; export { createEnv };