zod-config
Version:
Load configuration variables from multiple sources with flexible adapters, ensuring type safety with Zod.
126 lines (123 loc) • 3.21 kB
TypeScript
import * as z3 from 'zod/v3';
import * as z from 'zod/v4/core';
type SchemaConfig = z3.AnyZodObject | z.$ZodType<Record<string, unknown>>;
type ZodV4Output<T> = T extends z.$ZodType<any> ? z.infer<T> : never;
type InferredDataConfig<S extends SchemaConfig> = S extends z3.ZodType<infer T> ? T : ZodV4Output<S>;
type InferredErrorConfig<S extends SchemaConfig> = S extends z3.ZodType<infer T> ? z3.ZodError<T> : S extends z.$ZodType<infer U> ? z.$ZodError<U> : never;
type BaseAdapter = {
/**
* Name of the adapter
*/
name: string;
/**
* Separator to use for creating nested objects from flat keys (e.g., "." or "_")
* When provided, keys like "database.host" or "database_host" will be converted to { database: { host: value } }
* Only top-level keys get split, nested keys are not affected.
*/
nestingSeparator?: string;
} & SharedConfigOptions;
/**
* Adapter type
*/
type Adapter<D extends SchemaConfig = SchemaConfig> = BaseAdapter & {
/**
* Read the config
*/
read: () => Promise<InferredDataConfig<D>>;
};
/**
* Synchronous adapter type
*/
type SyncAdapter<D extends SchemaConfig = SchemaConfig> = BaseAdapter & {
/**
* Read the config
*/
read: () => InferredDataConfig<D>;
};
type BaseConfig<S extends SchemaConfig = SchemaConfig> = {
/**
* Schema to validate the config against
*/
schema: S;
/**
* Function to call on success
*/
onSuccess?: (data: InferredDataConfig<S>) => void;
/**
* Function to call on error
*/
onError?: (error: InferredErrorConfig<S>) => void;
/**
* Logger to use
*/
logger?: Logger;
} & SharedConfigOptions;
/**
* Config type
*/
type Config<S extends SchemaConfig = SchemaConfig> = BaseConfig<S> & {
/**
* Adapters to use
*/
adapters?: Array<Adapter | SyncAdapter> | Adapter | SyncAdapter;
};
/**
* Synchronous config type
*/
type SyncConfig<S extends SchemaConfig = SchemaConfig> = BaseConfig<S> & {
/**
* Adapters to use
*/
adapters?: Array<SyncAdapter> | SyncAdapter;
};
/**
* Logger type
*/
type Logger = {
/**
* Log a warning
*/
warn: (message: string) => void;
};
/**
* Base adapter props
*/
type BaseAdapterProps = {
/**
* Regular expression to match keys to be processed.
*/
regex?: RegExp;
} & SharedConfigOptions;
/**
* Shared config options between global config and adapter config
*/
type SharedConfigOptions = {
/**
* Whether to suppress errors
*/
silent?: boolean;
/**
* How to handle casing differences.
*/
keyMatching?: KeyMatching;
/**
* Function to transform key-value pairs before processing.
* If the function returns false, the key-value pair will be dropped.
*/
transform?: Transform;
};
/**
* Transform type
*/
type Transform = (obj: {
key: string;
value: unknown;
}) => {
key: string;
value: unknown;
} | false;
/**
* Key matching type
*/
type KeyMatching = "lenient" | "strict";
export { Adapter as A, BaseAdapterProps as B, Config as C, InferredDataConfig as I, Logger as L, SchemaConfig as S, SyncConfig as a, SyncAdapter as b };