Simplify type-safe configuration from multiple sources with zod-config
Tags: zod, typescript, productivity, opensource
Published: 2024-02-05 11:44:54

## Introduction
Managing configurations in my TypeScript projects is becoming boring as I always have to write the same boilerplate code to load and validate them. I've been using [zod](https://zod.dev/) for a while now, and it's been a great help in ensuring that my configurations are of the correct type. But what if I want to load configurations from multiple sources? I would have to write the code to load and merge them "manually"... don't like that 🙉. 

For that reason, I decided to create a library that handles all of this for me, welcome [zod-config](https://github.com/alexmarqs/zod-config) 🚀. The primary motivation behind it was to eliminate repetitive boilerplate code and ensure type safety in configuration management across multiple sources at once.

## Let's know more about zod-config
[zod-config](https://github.com/alexmarqs/zod-config)  is a typescript library that helps you manage your configurations in a type-safe way. It integrates with `zod` to provide robust type checking and validation. Some of the key features:

- Combine multiple adapters to load the configuration from different sources;
- We deeply merge the configuration from different sources, following the order of the adapters provided; 
- Create your own adapters easily; We expose all the types/interfaces you need to create your own adapters;
- You can use callback functions to handle errors and success due to the async nature of the adapters;


## How to use it

### Installation
```bash
npm install zod-config
```

### Quick Start

[zod-config](https://github.com/alexmarqs/zod-config) provides a `loadConfig` function that takes a Zod Object schema and returns a promise that resolves to the configuration object with the correct type. To use adapters, you should provide them in the `adapters` property. If you don't provide any adapter, we will use a default adapter (process.env). This library provides some built in adapters to load the configuration from different sources via modules. You can easily import them from `zod-config/<built-in-adapter-module-name>` (check examples below).  
For API Reference, please refer to the [README](https://github.com/alexmarqs/zod-config#readme). 

#### Some examples of usage:

```ts
import { z } from 'zod';
import { loadConfig } from 'zod-config';
import { envAdapter } from 'zod-config/env-adapter';
import { jsonAdapter } from 'zod-config/json-adapter';
import { dotEnvAdapter } from 'zod-config/dotenv-adapter';

// Schema to validate the configuration
const schemaConfig = z.object({
  port: z.string().regex(/^\d+$/),
  host: z.string(),
});

// 1) *** Using Default Adapter (process.env) ***
const config1 = await loadConfig({
  schema: schemaConfig
});

// 2) *** Using Env Adapter (process.env) with prefix key for filtering ***
const config2 = await loadConfig({
  schema: schemaConfig,
  adapters: envAdapter({ 
    prefixKey: 'MY_APP_',
    // customEnv: {...} // you can also provide a custom env object
});

// 3) *** Using JSON Adapter ***
const filePath = path.join(__dirname, 'config.json');

const config3 = await loadConfig({
  schema: schemaConfig,
  adapters: jsonAdapter({ path: filePath }),
});

// 4) *** Using Dotenv Adapter (peer dep. dotenv needed) ***
const filePath = path.join(__dirname, '.env');

const config4 = await loadConfig({
  schema: schemaConfig,
  adapters: dotEnvAdapter({ path: filePath }),
});

// 5) *** Combining multiple adapters ***
const config5 = await loadConfig({
  schema: schemaConfig,
  adapters: [
    jsonAdapter({ path: filePath }),
    envAdapter(),
  ],
});

// 6) *** Using callbacks *** 
loadConfig({
  schema: schemaConfig,
  onError: (error) => {
    console.error('An error occurred while loading the configuration:', error);
  },
  onSuccess: (config) => {
    console.log('Configuration loaded successfully:', config);
  },
});
```

## Community

This library is referenced in the official Zod documentation as part of its ecosystem in the section "Powered by Zod", check it out [here](https://zod.dev/?id=powered-by-zod).

For any suggestion, improvement, or bug report, please open an issue or a PR in the [github repository](https://github.com/alexmarqs/zod-config). I would love to hear your feedback 💪.


## Before you leave... I have a question for you!

If you reached this point, it means you are a type safety enthusiast and you are probably interested in working with modern technologies and tools! 

Would you like to be part of a talented team that is helping the energy transition? We are hiring at [epilot](https://epilot.cloud/en/)! Check out [our career page](https://epilot.recruitee.com/) or reach out to [my Twitter](https://twitter.com/alexlmarques) if you have any questions.