The modern way to handle and validate your application configuration with any standard-schema-compliant validation library.
Figue is a modern configuration management library for Node.js. It is designed to be easy to use, flexible, it can used in any environment, and can be used with any standard-schema-compliant validation library, like zod or valibot.
Think of it as a modern version of convict but simpler, cross env and using battle tested validation libraries.
- Environment variables support
- Validation with any standard-schema-compliant validation library
- Flat object support
- Multiple sources of configuration
- Type-safe configuration
- Composable configuration
Install package:
# pnpm
pnpm install figue
# npm
npm install figue
# yarn
yarn install figue
Import:
// ESM
import { defineConfig } from 'figue';
// CommonJS
const { defineConfig } = require('figue');
Use the defineConfig
function to define your configuration, here with valibot:
import { defineConfig } from 'figue';
import * as v from 'valibot';
const { config } = defineConfig(
{
env: {
doc: 'Application current environment',
default: 'development',
schema: v.picklist(['development', 'production', 'test']),
env: 'NODE_ENV',
},
port: {
doc: 'Application port to listen',
schema: v.pipe(v.union([v.number(), v.string()]), v.transform(Number)),
default: 3000,
env: 'PORT',
},
db: {
host: {
doc: 'Database server url',
schema: v.pipe(v.string(), v.url()),
default: 'http://localhost:5432',
env: 'APP_DB_HOST',
},
username: {
doc: 'Database server username',
schema: v.string(),
default: 'pg',
env: 'APP_DB_USERNAME',
},
password: {
doc: 'Database server password',
schema: v.string(),
default: '',
env: 'APP_DB_PASSWORD',
},
},
},
{
envSource: process.env,
},
);
console.log(config);
// {
// env: "development",
// port: 3000,
// db: {
// url: "https://localhost",
// username: "pg",
// password: "",
// },
// }
You can see more examples in the demo folder.
- Figue with zod: demo/figue-zod.ts
- Figue with valibot: demo/figue-valibot.ts
Use the envSource
key of the second argument of defineConfig
to specify the source of the environment variables:
const { config } = defineConfig(
{
/* ... */
},
{
envSource: process.env,
},
);
In some case you don't have access to a process.env
variable, like with vite
, just simply load what stores your env variables :
const { config } = defineConfig(
{
/* ... */
},
{
envSource: import.meta.env,
},
);
You can even specify you custom environment storage as long as it's a simple flat object map, for example:
const { config } = defineConfig(
{
env: {
doc: 'Application current environment',
default: 'development',
schema: z.enum(['development', 'production', 'test']),
env: 'NODE_ENV',
},
/* ... */
},
{
envSource: {
NODE_ENV: 'development',
PORT: '3000',
APP_DB_HOST: 'localhost',
APP_DB_USERNAME: 'pg',
APP_DB_PASSWORD: '',
},
},
);
If, for some reason, you have multiple sources of environment variables, you can use the envSources
key of the second argument of defineConfig
to specify an array of sources:
const { config } = defineConfig(
{
/* ... */
},
{
envSource: [import.meta.env, myEnvs],
},
);
You can use the getDefaults
key of the second argument of defineConfig
to specify a function that will be called to get some defaults:
const { config } = defineConfig(
{
env: {
doc: 'Application current environment',
default: 'development',
schema: z.enum(['development', 'production', 'test']),
env: 'NODE_ENV',
},
port: {
doc: 'Application port to listen',
schema: z.coerce.number().int().positive(),
default: 3000,
env: 'PORT',
},
},
{
envSource: {
PORT: 3001,
},
// The config argument is build from the config definition defaults and the envSources
// Typically you will use it to override some defaults based the config
getDefaults: ({ config }) => ({
port: config.env === 'test' ? 4444 : config.port,
}),
},
);
You can also use the defaults
property of the second argument of defineConfig
to specify some static defaults (for example taken from a json file):
const { config } = defineConfig(
{
/* ... */
},
{
// Either an array of config partial...
defaults: [
{
port: 4444,
},
],
// ... or a single config partial
defaults: {
port: 4444,
},
},
);
Convict is meant to be used in node based environnement, it needs to have access to global variables that may may not be present in some environnement (like process
, global
), and it also imports fs
.
Figue is the french for fig -> con-fig.
- Clone this repository
- Install dependencies using
pnpm install
- Run interactive tests using
pnpm dev
This project is crafted with ❤️ by Corentin Thomasset. If you find this project helpful, please consider supporting my work.
Fig icons created by Freepik - Flaticon
This project is under the MIT license.