Usage
bunfig is a smart configuration loader designed specifically for Bun projects. It provides a simple yet powerful way to manage your application's configuration.
Basic Usage
The simplest way to use bunfig is with the config function:
import { config } from 'bunfig'
interface MyConfig {
port: number
host: string
}
// Load config using a name
const myConfig = await config<MyConfig>('my-app')
// Or with explicit options
const myConfig = await config<MyConfig>({
name: 'my-app',
defaultConfig: {
port: 3000,
host: 'localhost',
},
})
// Using an alias for alternative config file names
const myConfig = await config<MyConfig>({
name: 'my-app',
alias: 'app',
defaultConfig: {
port: 3000,
host: 'localhost',
},
})Configuration File Resolution
bunfig searches for your configuration files in the following priority order:
1. Local Directory (Project-specific configs)
First, bunfig looks in your project directory for:
{name}.config.{ts,js,mjs,cjs,json}.{name}.config.{ts,js,mjs,cjs,json}{name}.{ts,js,mjs,cjs,json}.{name}.{ts,js,mjs,cjs,json}
2. Home Directory (Global configs)
If no local configuration is found, bunfig checks your home directory following the XDG Base Directory specification:
~/.config/{name}/config.{ts,js,mjs,cjs,json}~/.config/{name}/{name}.config.{ts,js,mjs,cjs,json}
This allows you to store global configuration settings that apply across all your projects using the same configuration name.
3. Package.json sections
If no file-based configuration is found, bunfig looks for a configuration section in your package.json file.
For example, if your name is "my-app", it will look for:
Local directory:
my-app.config.ts.my-app.config.tsmy-app.ts.my-app.ts(and the same for other supported extensions)
Home directory (if no local file found):
~/.config/my-app/config.ts~/.config/my-app/my-app.config.ts(and the same for other supported extensions)
Package.json:
{
"my-app": {
"port": 4000,
"host": "example.com"
}
}When you specify an alias, bunfig will also check for files with the alias name using the same patterns if no file with the primary name is found.
Configuration Aliases
You can use aliases to provide alternative configuration file names:
const tlsConfig = await loadConfig({
name: 'tlsx',
alias: 'tls',
defaultConfig: {
domain: 'example.com',
port: 443,
},
})This is useful for:
- Maintaining backward compatibility when renaming configurations
- Supporting multiple naming conventions
- Providing fallbacks for different environments
When both a primary config file and an alias config file exist, the primary file takes precedence.
Alias resolution applies to both local and home directories:
- Local:
tlsx.config.ts→tls.config.ts - Home:
~/.config/tlsx/config.ts→~/.config/tlsx/tls.config.ts→~/.config/tls/config.ts→~/.config/tls/tls.config.ts
The alias feature also works when looking for config in package.json - if a section with the primary name isn't found, bunfig will look for a section with the alias name.
Advanced Usage
Using loadConfig Directly
For more control over the configuration loading process, you can use the loadConfig function:
import type { Config } from 'bunfig'
import { loadConfig } from 'bunfig'
interface MyConfig {
port: number
host: string
features: {
auth: boolean
api: boolean
}
}
const options: Config<MyConfig> = {
name: 'my-app',
cwd: './config', // custom directory to search in
defaultConfig: {
port: 3000,
host: 'localhost',
features: {
auth: false,
api: true,
},
},
}
const config = await loadConfig(options)Type Generation
bunfig includes a utility to generate TypeScript types for your configuration files:
import { generateConfigTypes } from 'bunfig'
generateConfigTypes({
configDir: './config', // directory containing your config files
generatedDir: './types', // output directory for generated types
})This will generate a type definition file containing all available configuration names based on the files in your config directory.
Dynamic Config Names
To get strict type checking of config names without generating files, enable the provided build plugin. It exposes a virtual module that turns ConfigNames into a union of your config filenames. Without the plugin, ConfigNames is string by design.
If your TypeScript setup filters ambient types and you see a missing type error for virtual:bunfig-types, add:
/// <reference types="bunfig" />or configure tsconfig.json:
{
"compilerOptions": {
"types": ["bunfig"]
}
}See the README section “Dynamic Config Name Types (no files on disk)” for a full example.
Advanced: narrow by name
For the narrowest types with no on-disk generation, use the plugin and ConfigOf<N>:
import type { ConfigOf } from 'bunfig'
import { loadConfig } from 'bunfig'
const cfg = await loadConfig<ConfigOf<'app'>>({
name: 'app',
defaultConfig: { /* ... defaults ... */ } as ConfigOf<'app'>,
})When the plugin is not active, ConfigOf<N> falls back to a broad shape so your code still compiles.
API Reference
config<T>(nameOrOptions)
The main function to load configuration.
nameOrOptions: Either a string (config name) or a configuration object- Returns:
Promise<T>where T is your config type
loadConfig<T>(options)
Low-level configuration loader with more options.
Options:
name: The name of your configurationalias: An alternative name to check for config files (optional)cwd?: Working directory to search for config files (defaults to process.cwd())defaultConfig: Default configuration values
generateConfigTypes(options)
Generates TypeScript types for your configuration files.
Options:
configDir: Directory containing configuration filesgeneratedDir: Output directory for generated type definitions
Configuration File Format
Your configuration file can be in any of the supported formats. Here's an example using TypeScript:
// my-app.config.ts (local)
export default {
port: 4000,
host: 'localhost',
features: {
auth: true,
api: true,
},
}Or in your home directory:
// ~/.config/my-app/config.ts (global)
export default {
port: 8080,
host: 'production.example.com',
features: {
auth: true,
api: true,
},
}The configuration file's values will be deeply merged with your default configuration, with file values taking precedence.
Best Practices
- Always define an interface for your configuration
- Provide sensible default values
- Use TypeScript for better type safety
- Keep configuration files in a dedicated directory
- Use the type generation feature to ensure type safety across your project
- Use aliases for backward compatibility when renaming configurations
- Use home directory configs (
~/.config/$name/) for global settings that apply across projects - Use local configs for project-specific overrides
Browser Support
bunfig is primarily designed for Bun projects running in Node.js environments. While the core functionality works in browsers, some features like file system operations are not available in browser environments.
For browser usage, you should:
- Pre-bundle your configuration during build time
- Use the browser-safe APIs only
- Consider using environment-specific configuration loading strategies