CorentinTh/figue được TopGit xếp vào nhóm dự án mã nguồn mở, với 23 sao trên GitHub, viết chủ yếu bằng TypeScript. Configuration management library, like convict but with modern validation libraries
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
The modern way to handle and validate your application configuration with any standard-schema-compliant validation library.
Introduction
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.
Features
Environment variables support
Validation with any standard-schema-compliant validation library
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:
You can specify multiple environment variable names for a single configuration field by providing an array of strings. Figue will use the first environment variable that is found in your environment sources.
This feature is particularly useful when:
Supporting multiple deployment environments with different environment variable naming conventions
Migrating from legacy environment variable names while maintaining backward compatibility
Providing fallback options for missing environment variables
const { config } = defineConfig(
{
port: {
doc: 'Application port to listen',
schema: z.coerce.number(),
default: 3000,
// Will use PORT if available, otherwise APP_PORT, otherwise SERVER_PORT
env: ['PORT', 'APP_PORT', 'SERVER_PORT'],
},
database: {
host: {
doc: 'Database host',
schema: z.string(),
default: 'localhost',
// Useful for supporting legacy environment variable names
env: ['DATABASE_HOST', 'DB_HOST', 'LEGACY_DB_URL'],
},
},
workerId: {
doc: 'Worker identifier',
schema: z.string().optional(),
// Or using some plateform specific environment variable
env: ['WORKER_ID', 'HEROKU_DYNO_ID', 'RENDER_INSTANCE_ID'],
},
},
{
envSource: process.env,
},
);
Some caveats:
If none of the specified environment variables are found, Figue will fall back to the default as expected when no env key is present.
If a variable is found but its value is nullish or falsy (like an empty string, or undefined), Figue will still consider it as set and use that value. If you want to ignore such values, you should handle that in your schema validation.
Ensure that the order of environment variables in the array reflects their priority, as Figue will use the first one it finds.
Get defaults
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,
},
},
);
Cross-field validation
Sometimes a single schema isn't enough — a field's validity may depend on another field's value. For these cases, add a validate function to any field. It runs after every per-field schema check has passed, and receives the fully-validated config:
import { defineConfig, validator } from 'figue';
import * as v from 'valibot';
type Config = {
adapters: { id: string; url: string }[];
defaultAdapterId: string;
};
const { config } = defineConfig({
adapters: {
doc: 'Available resource adapters',
schema: v.array(v.object({ id: v.string(), url: v.string() })),
default: [],
env: 'ADAPTERS',
},
defaultAdapterId: {
doc: 'Default adapter id (must reference one of `adapters[].id`)',
schema: v.string(),
default: '',
env: 'DEFAULT_ADAPTER_ID',
validate: validator<Config>(({ value, config }) => {
if (!config.adapters.some(a => a.id === value)) {
return `must match one of adapters[].id (got "${value}")`;
}
}),
},
});
Co-locating the rule with the field it belongs to keeps things readable, even when your config definition is split across modules.
Return contract — the function can either throw or return:
Return value
Meaning
void / undefined / true
passes
false
generic "Validation failed at <path>" issue
string
used as the issue message
{ message, path? }
a fully-formed issue (path defaults to the current field)
ValidateIssue[]
multiple issues from a single rule
throw new Error(msg)
caught; error.message becomes the issue
All issues from cross-field rules are aggregated into a single ConfigValidationError, just like schema errors.
Typing the config argument — by default config is loosely typed (any) so you don't have to declare anything. When you want full IntelliSense on the cross-referenced fields, wrap your function with the validator<Config>(...) helper as shown above. It's a no-op at runtime, purely a type hint.
Note — validate only runs once every field's schema has validated successfully, so you can trust that config is fully typed and coerced.
What's wrong with convict?
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?
Figue is the french for fig -> con-fig.
Development
Clone this repository
Install dependencies using pnpm install
Run interactive tests using pnpm dev
Credits
This project is crafted with ❤️ by Corentin Thomasset.
If you find this project helpful, please consider supporting my work.
GitHub topics của CorentinTh/figue: "config", "configuration-management", "env", "environment-variables", "standard-schema", "valibot", "zod". TopGit xếp repo vào nhóm mã nguồn mở.
CorentinTh/figue có phải mã nguồn mở không?
Có — CorentinTh/figue phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/CorentinTh/figue.
CorentinTh/figue có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho CorentinTh/figue. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
CorentinTh/figue còn đang phát triển không?
Commit gần nhất trên CorentinTh/figue là 1 tháng trước (theo timestamp GitHub). Repo có 2 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
CorentinTh/figue dùng license gì?
CorentinTh/figue phát hành theo license MIT. Nên mở file LICENSE trên GitHub để xác nhận — license metadata đôi khi lệch với thực tế dự án.
Đọc thêm về CorentinTh/figue ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/CorentinTh/figue là nguồn chính thức.