Smart configuration loader for libraries, apps, and CLIs built utilizing Bun.
- 🔄 Smart Config: intelligent configuration loading with multiple sources
- 🏠 Home Directory Support: global configurations via
~/.config/$name/
- 🌐 Universal: optimized for both Bun & browser environments
- 🪶 Lightweight: zero dependencies, built on native modules
- 💪 Type-Safe: fully typed configurations with generated type definitions
- 🌍 Environment Variables: automatic environment variable support based on config name
- 🛠️ CLI Tools: powerful & easy-to-use CLI
- 📦 Flexible: supports multiple config file formats (.ts, .js, .mjs, .cjs, .json, .mts, .cts)
- 🔄 Aliases: support for alternative configuration file names
bun install -d bunfig
If you are building any sort of Bun project, you can use the loadConfig
function to load your configuration from files:
import type { Config } from 'bunfig'
import { loadConfig } from 'bunfig'
interface MyLibraryConfig {
port: number
host: string
}
const options: Config<MyLibraryConfig> = {
name: 'my-app', // required
cwd: './', // default: process.cwd()
defaultConfig: { // default: {}
port: 3000,
host: 'localhost',
},
}
const resolvedConfig = await loadConfig(options)
console.log(resolvedConfig) // { port: 3000, host: 'localhost' }, unless a config file is found
Tip
bunfig will search for configuration files in this priority order:
- Local directory:
$name.config.{ts,js,mjs,cjs,json}
(or.$name.config.{ts,js,mjs,cjs,json}
) in your project - Home directory:
~/.config/$name/config.{ts,js,mjs,cjs,json}
for global settings - Package.json: configuration sections in your package.json file
For minimalists, it also supports .$name.{ts,js,mjs,cjs,json}
and $name.{ts,js,mjs,cjs,json}
patterns in both local and home directories.
bunfig supports global configuration files in your home directory following the XDG Base Directory specification. This is useful for:
- Global tool settings that apply across all your projects
- Personal preferences that you want to use everywhere
- Default configurations that can be overridden per project
// ~/.config/my-app/config.ts (global configuration)
export default {
theme: 'dark',
defaultPort: 8080,
globalFeatures: ['feature1', 'feature2'],
}
// ./my-app.config.ts (project-specific override)
export default {
defaultPort: 3000, // Override global setting for this project
projectSpecific: true,
}
The final configuration will be deeply merged, with local project settings taking precedence over global home directory settings.
You can specify an alias to check for alternative config file names when the primary name doesn't exist:
const config = await loadConfig({
name: 'tlsx',
alias: 'tls', // Alternative name to check if tlsx.config.* doesn't exist
defaultConfig: {
domain: 'example.com',
port: 443,
},
})
This will check for both tlsx.config.ts
and tls.config.ts
(and other variations) in both local and home directories, using the first one it finds. This is useful for maintaining backward compatibility when renaming configurations or providing fallbacks.
Bunfig automatically checks for environment variables based on the config name. Environment variables take precedence over default values but are overridden by config files.
You can disable this feature by setting checkEnv: false
in your config options:
const options = {
name: 'my-app',
defaultConfig: { /* ... */ },
checkEnv: false, // Disable environment variable checking
}
The naming convention for environment variables is:
[CONFIG_NAME]_[PROPERTY_NAME]
For nested properties, use underscores to separate the levels:
[CONFIG_NAME]_[NESTED_PROPERTY_PATH]
Example:
// With a config name of "my-app"
const options = {
name: 'my-app',
defaultConfig: {
port: 3000,
host: 'localhost',
database: {
url: 'postgres://localhost:5432',
user: 'admin',
},
},
}
// These environment variables would be automatically used if set:
// MY_APP_PORT=8080
// MY_APP_HOST=example.com
// MY_APP_DATABASE_URL=postgres://production:5432
// MY_APP_DATABASE_USER=prod_user
For array values, you can use a JSON string or comma-separated values:
MY_APP_ALLOWED_ORIGINS=["https://example.com","https://api.example.com"]
// or
MY_APP_ALLOWED_ORIGINS=https://example.com,https://api.example.com
For browser environments, use the loadConfig
function from the browser-specific entry point to load your configuration from an API endpoint:
import type { Config } from 'bunfig'
import { loadConfig } from 'bunfig/browser'
interface MyLibraryConfig {
port: number
host: string
}
const options: Config<MyLibraryConfig> = {
name: 'my-app',
endpoint: '/api/config', // required for browser environment
defaultConfig: {
port: 3000,
host: 'localhost',
},
headers: { // optional custom headers
'Authorization': 'Bearer token',
'X-Custom-Header': 'value',
},
}
const resolvedConfig = await loadConfig(options)
In the browser:
- The
endpoint
parameter is required to specify where to fetch the configuration - Custom headers can be provided to authenticate or customize the request
- Default headers (
Accept
andContent-Type
) are automatically included - If the fetch fails, the default configuration is used as a fallback
Alternatively, you can use the config
function to load your configuration in server environments:
import type { Config } from 'bunfig'
import { config } from 'bunfig'
interface MyAppOrLibraryConfig {
port: number
host: string
}
const options: Config<MyAppOrLibraryConfig> = {
name: 'my-app', // required to know which config file to load
cwd: './', // default: process.cwd()
defaultConfig: { // default: {}
port: 3000,
host: 'localhost',
},
}
const resolvedConfig = await config(options)
The config function is a wrapper around the loadConfig
function and is useful for loading configuration in a more flexible way. It accepts an options object with the following properties:
name
: The name of the config file to load.cwd
: The current working directory to load the config file from.defaultConfig
: The default config to use if no config file is found.
For browser usage, see the Browser Environment section above.
bun test
Please see our releases page for more information on what has changed recently.
Please review the Contributing Guide for details.
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
For casual chit-chat with others using this package:
Join the Stacks Discord Server
“Software that is free, but hopes for a postcard.” We love receiving postcards from around the world showing where bunfig
is being used! We showcase them on our website too.
Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎
We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.
The MIT License (MIT). Please see LICENSE for more information.
Made with 💙