Sources
Sources define where the library reads your configuration from, such as files or environment variables.
By default, if no parser is specified, @layerfig/config
uses its internal JSON parser for .json
files.
export const config = new ConfigBuilder({ validate: (finalConfig) => schema.parse(finalConfig)}) .addSource("base.json") .addSource("prod.json") .build();
{ "appURL": "http://localhost:3000"}
{ "appURL": "http://my-app.com"}
Other File Extensions
Section titled “Other File Extensions”To support various project needs, we provide parsers for other common configuration file formats:
… or create your own parser.
Environment Variables
Section titled “Environment Variables”Consider the following scenario:
Your application’s configuration files are committed to version control and used to build a Docker image for production. When running this image locally for debugging, any change to a configuration value requires rebuilding the image. This process can be slow and results in testing a modified image rather than the actual production build.
To avoid this, use ConfigBuilder.createEnvVarSource()
to override configuration values at runtime without modifying the source files:
import { ConfigBuilder } from "@layerfig/config";import { schema } from "./schema";
export const config = new ConfigBuilder({ validate: (finalConfig) => schema.parse(finalConfig)}) .addSource("base.json") .addSource(ConfigBuilder.createEnvVarSource()) .build();
By default, the library expects environment variables with the following structure:
- Prefix:
"APP"
- Prefix separator:
"_"
- Nested key separator:
"__"
For example, the environment variable APP_port
overrides the port
key in your configuration.
Example Usage
Section titled “Example Usage”Suppose your base.json
contains:
{ "appURL": "http://localhost:4444", "port": 4444, "appEnv": "local"}
Define your schema and load the sources:
export const config = new ConfigBuilder({ validate: (finalConfig, z) => { const schema = z.object({ appURL: z.url(), port: z.coerce.number().int().positive(), appEnv: z.enum(["local", "dev", "prod"]) });
return schema.parse(finalConfig) }}) .addSource("base.json") .addSource(ConfigBuilder.createEnvVarSource()) .build();
Run the application with overrides:
APP_appEnv=prod node index.js
Since the environment variable source is added last, its values take precedence.
Overriding Nested Objects
Section titled “Overriding Nested Objects”Use __
(double underscores) as a separator to target nested keys:
const AppConfigSchema = z.object({ api: z.object({ vendor: z.object({ aws: z.object({ apiToken: z.string(), }), }), }),});
const config = new ConfigBuilder(AppConfigSchema) .addSource("base.json") .addSource(ConfigBuilder.createEnvVarSource()) .build();
APP_api__vendor__aws__apiToken=12345 node index.js
Customizing Environment Variable Settings
Section titled “Customizing Environment Variable Settings”You can customize the prefix, prefix separator, and nested-key separator:
const config = new ConfigBuilder(AppConfigSchema) .addSource("base.json") .addSource( ConfigBuilder.createEnvVarSource({ prefix: "VULCAN", prefixSeparator: "--", separator: "----", }) ) .build();
VULCAN--api----vendor----aws----apiToken=12345 node index.js