⚠️ Warning, brek v3 contains breaking changes! See the Getting Started guide for more information.
Brek is a powerful, safe, and easy-to-use configuration library for Node.js. It’s structured, typed, and designed for dynamic configuration loading, making it perfect for securely managing secrets (e.g., AWS Secrets Manager). Written in TypeScript. Sponsored by Aeroview.
config/default.json
{
"foo": "bar",
"baz": {
"qux": 42
}
}
blah.ts
import {getConfig} from "brek";
const {foo, baz} = getConfig();
console.log(foo); // "bar"
console.log(baz.qux); // 42
console.log(baz.quux); // undefined and Typescript will throw an error at compile time
// Enjoy full autocompletion and type safety! 🚀
🔒 Out-of-the-box Typescript support
- Turn your runtime errors into safer compile-time errors! Automatically generated Typescript type definition for configuration object
😃 Easy-to-use & stable
- All settings are in simple, logic free
.json
files. - Adds structure and organization to your configuration files
- Easily see what is being overridden and where
- Comprehensive yet easy to understand documentation
- Small, modular, and unit-tested codebase written in Typescript.
- No dependencies!
💪 Flexible & powerful
- Differentiates between concepts such as
environment
,deployment
, anduser
and provides an out-of-the-box solution with sensible merge strategy - Provides for overrides via CLI without polluting the CLI argument namespace
- Fast. Runtime processing is done once during app initialization only.
- Put environment variables directly into .json files
🤖 Dynamic loading
- Great for AWS Secrets Manager, AWS Parameter Store, HashiCorp Vault, or custom dynamic runtime functions
- Any custom logic lives in loaders, keeping your config files logic-free
- Provides an easy sharable and reusable plugin interface for sharing or re-use
- Getting Started
- Configuration Rules
- Configuration Merge Strategy
- Using CLI/ENV Overrides
- Environment Variables in Config Files
- Loaders
- API Reference
- CLI Reference
- Recommended Best Practices
- Usage with AWS Lambda
- Debugging
- Known Issues
- Support, Feedback, and Contributions
- Why is it called brek?
- Sponsorship
- Other Useful Libraries
To install and get started with brek
, see our Getting Started guide.
-
default.json
is required, everything else is optional. Recommended practice is thatdefault.json
contains all of your "local development" settings. -
All configuration files must be a subset of
default.json
. Think of them simply as overrides to the default. In Typescript terms, configuration files must be of typePartial<Config>
. -
A property's type should not change simply because of a different environment, user, or deployment. This is basically saying the same as above.
-
Loaders always must return a string. If you need to return a different type, you can use
JSON.parse()
or similar. -
Arrays should be homogenous (not of mixed types).
Brek uses a simple and intuitive merge strategy, with the goal of making it easy to understand what is being overridden and where. You can specify configuration overrides for different environments, deployments, and users.
Configurations are merged in this order, with the later ones overriding the earlier ones:
- default.json
- environment file
- deployment file
- user file
- CLI/env overrides
Which of these sources to choose depends on the presence of certain process.env
configuration variables:
process.env | conf file |
---|---|
ENVIRONMENT , NODE_ENV |
/conf/environments/[ENVIRONMENT].json |
DEPLOYMENT |
/conf/deployments/[DEPLOYMENT].json |
USER |
/conf/users/[USER].json |
A few notes:
ENVIRONMENT
takes precedence overNODE_ENV
if both are set. This is useful for local development, or to not be tied to theNODE_ENV
convention (ie, if you have a package that usesNODE_ENV
for something else).USER
is usually provided by default by UNIX environments (tryconsole.log(process.env.USER)
)- Arrays and loaders are simply replaced, not merged.
You specify these by setting the appropriate process.env
variables. For example, to use the production
environment, set NODE_ENV=production
or ENVIRONMENT=production
.
You can use the BREK
environment variable to override properties via CLI/ENV. BREK
must be valid JSON. Using jq
simplifies dynamic JSON construction, ensures proper quoting, and makes it easier to handle environment variables.
# Override the a.b property
BREK=$(jq -n '{a: {b: "q"}}') ts-node src/index.ts
# Override the postgres property wth an environment variable
DATABASE_URL="postgres://user:pass@localhost:5432/db"
BREK=$(jq -n --arg db "$DATABASE_URL" '{postgres: $db}') ts-node src/index.ts
You can use environment variables as values by wrapping it in ${...}
. For example, to use environment variable FOO
, use ${FOO}
. This will translate to process.env.FOO
. These will always be typed as strings. Example config file:
{
"foo": "${FOO}"
}
Loaders are custom functions that are called during startup (run-time). This can be used to do anything, such as fetching secrets from AWS Secrets Manager, or any other dynamic runtime operation. They can be Promise/async/await based.
Quick example:
config/default.json
{
"foo": {
"[fetchSecret]": {
"key": "demo"
}
}
}
To learn more about loaders, see the Loaders documentation.
Returns the configuration object.
Preloads the configuration. Loads the configuration files from disk, merges them, resolves any loaders, and writes the final configuration to config.json
. This is not typically called directly, but you can if you want to instead of using the CLI.
You can call the binary brek
to perform various operations. You can use npx brek
or in your package.json
scripts.
Preloads the configuration. Loads the configuration files from disk, merges them, resolves any loaders, and writes the final configuration to config.json
.
Writes the types to config/Config.d.ts
unless otherwise specified. This must be called whenever default.json
is changed.
default.json
should contain all of your local development settings, and then "progressively enhance" from there.- Use AWS Secrets Manager or Hashicorp Vault to store your sensitive information and use a loader to load them.
AWS Lambda has a read-only file system, except for the temporary /tmp
directory, which is writable. To handle this, set the environment variable BREK_WRITE_DIR
to /tmp
.
You may also want to run brek load-config
after your build step. Example:
{
"scripts": {
"build": "tsc",
"load-config": "ENVIRONMENT=prod BREK_WRITE_DIR=/tmp brek load-config",
"prepare": "npm run build && npm run load-config"
}
}
If the loaders must be executed during runtime, then you can use the await loadConfig()
method in your Lambda handler to ensure the configuration is loaded before your function executes. Don't forget to include BREK_WRITE_DIR=/tmp
in your Lambda environment variables.
You can set the BREK_DEBUG
environment variable to see debug output. Example:
BREK_DEBUG=1 ts-node src/index.ts
Use with caution! This may output sensitive information to the console.
-
Some IDEs (particularly IntelliJ/Webstorm) occasionally have some issues with caching of the generated
Conf.d.ts file
(which is stored in yourconf
folder). If you run into this problem, restarting your TS service. -
If you're using AWS Lambda, see the Usage with AWS Lambda section.
-
If the configuration ever gets out of date, you'll need to do one or more of the following:
- Call
brek write-types
to regenerate the type declaration file and delete the disk cache (config.json
) - Make sure you're calling
brek load-config
orloadConfig(): Promise<void>
before app startup - Restart your app to clear cache in memory
- Call
- ⭐ Star this repo if you like it!
- 🐛 Open an issue for bugs or suggestions.
- 🤝 Submit a PR to
main
— all tests must pass.
Brek stands for Blocking Resolution of Environment Keys. TBH, it just sounded cool and was available on NPM 😄.
Aeroview is a lightning-fast, developer-friendly, and AI-powered logging IDE. Get started for free at https://aeroview.io.
Want to sponsor this project? Reach out.
- autorel: Automate semantic releases based on conventional commits. Similar to semantic-release but much simpler.
- hoare: An easy-to-use, fast, and defensive JS/TS test runner designed to help you to write simple, readable, and maintainable tests.
- jsout: A Syslog-compatible, small, and simple logger for Typescript/Javascript projects.
- cjs-mock: NodeJS module mocking for CJS (CommonJS) modules for unit testing purposes.
- typura: Simple and extensible runtime input validation for TS/JS, written in TS.