DEV Community

Alexandre Marques
Alexandre Marques

Posted on

Simplify type-safe configuration from multiple sources with zod-config

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 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 🚀. 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 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

npm install zod-config
Enter fullscreen mode Exit fullscreen mode

Quick Start

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.

Some examples of usage:

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);
  },
});
Enter fullscreen mode Exit fullscreen mode

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.

For any suggestion, improvement, or bug report, please open an issue or a PR in the github repository. 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! Check out our career page or reach out to my Twitter if you have any questions.

Top comments (0)