API Reference
This document provides detailed information about bunfig's API.
Core Functions
config<T>
The main function to load configuration.
async function config<T>(
nameOrOptions: string | Config<T> = { defaultConfig: {} as T }
): Promise<T>Parameters
nameOrOptions: Either a string (config name) or a configuration object- When string: Uses default options with the given name
- When object: Uses the provided configuration options
Example
// Using name only
const config1 = await config<MyConfig>('my-app')
// Using full options
const config2 = await config<MyConfig>({
name: 'my-app',
defaultConfig: {
port: 3000,
},
})
// Using an alias
const config3 = await config<MyConfig>({
name: 'my-app',
alias: 'app',
defaultConfig: {
port: 3000,
},
})loadConfig<T>
Low-level configuration loader with more control over the loading process.
async function loadConfig<T>({
name,
alias,
cwd,
defaultConfig,
checkEnv,
verbose,
arrayStrategy, // 'replace' | 'merge' (default 'replace')
}: Config<T>): Promise<T>Parameters
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 valuesarrayStrategy: Controls how arrays are merged. Defaults to'replace'(user-provided arrays replace defaults). Set to'merge'to concatenate arrays using bunfig's smart merge.
Example
const config = await loadConfig<MyConfig>({
name: 'my-app',
cwd: './config',
defaultConfig: {
port: 3000,
},
})
// With alias
const tlsConfig = await loadConfig<TlsConfig>({
name: 'tlsx',
alias: 'tls',
defaultConfig: {
domain: 'example.com',
},
})generateConfigTypes
Generates TypeScript types for your configuration files.
function generateConfigTypes(options: {
configDir: string
generatedDir: string
}): voidParameters
options.configDir: Directory containing configuration filesoptions.generatedDir: Output directory for generated type definitions
Example
generateConfigTypes({
configDir: './config',
generatedDir: './types',
})Types
Config<T>
The main configuration options interface.
interface Config<T> {
name: string
alias?: string
cwd?: string
endpoint?: string // browser
headers?: Record<string, string> // browser
defaultConfig: T
checkEnv?: boolean
verbose?: boolean
arrayStrategy?: 'replace' | 'merge'
}ConfigNames
Represents valid configuration names.
- With the build plugin active, it resolves to a string-literal union inferred from your
configdirectory (via a virtual module). - Without the plugin, it safely falls back to
stringusing an ambient declaration shipped with bunfig.
// With plugin: type could be 'app' | 'auth' | 'database'
// Without plugin: type is stringIf your TS setup needs it, you can explicitly reference the fallback types:
/// <reference types="bunfig" />or in tsconfig.json:
{
"compilerOptions": {
"types": ["bunfig"]
}
}ConfigByName and ConfigOf<N>
With the build plugin active, bunfig exposes a mapping between configuration names and their default export types via a virtual module.
ConfigByName:{ 'name': typeof import('/abs/path/config/name.ext').default, ... }ConfigOf<N extends ConfigNames>: picks the config type for a givenN.
These enable narrow typing without generating files:
import type { ConfigOf } from 'bunfig'
const cfg = await loadConfig<ConfigOf<'app'>>({ name: 'app', defaultConfig: { /* ... */ } as ConfigOf<'app'> })Without the plugin, these types fall back to broad shapes so the code continues to typecheck.
Utility Functions
tryLoadConfig<T>
Attempts to load a config file from a specific path.
async function tryLoadConfig<T>(
configPath: string,
defaultConfig: T,
arrayStrategy?: 'replace' | 'merge'
): Promise<T | null>Parameters
configPath: Path to the configuration filedefaultConfig: Default configuration to merge with
Returns
- The merged configuration if successful
nullif the file doesn't exist or is invalid
Constants
defaultConfigDir
The default directory for configuration files.
const defaultConfigDir: string = resolve(process.cwd(), 'config')defaultGeneratedDir
The default directory for generated files.
const defaultGeneratedDir: string = resolve(process.cwd(), 'src/generated')Configuration File Resolution
bunfig searches for configuration files in the following priority order:
1. Local Directory Resolution
In your project directory, bunfig looks 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 Resolution
If no local configuration file 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 Configuration
If no file-based configuration is found, bunfig looks for a configuration section in your package.json file.
If an alias is provided, it will also check for files with the alias name using the same patterns if no file with the primary name is found.
Resolution Examples
For a configuration with name "my-app":
Local directory (project-specific):
my-app.config.ts.my-app.config.tsmy-app.ts.my-app.ts
Home directory (global, if no local file found):
~/.config/my-app/config.ts~/.config/my-app/my-app.config.ts
Package.json (if no file-based config found):
{
"my-app": {
"port": 4000,
"host": "example.com"
}
}The first file found in this order will be used. The contents will be deeply merged with the default configuration.
Error Handling
All functions that load configuration files handle errors gracefully:
- Missing files return the default configuration
- Invalid files are skipped
- Type mismatches are handled by returning the default configuration
- File system errors are caught and handled appropriately
Best Practices
Always provide type information when using
configorloadConfig:tsconst config = await config<MyConfig>('my-app')Use the type generation feature to ensure type safety:
tsgenerateConfigTypes({ configDir: './config', generatedDir: './types', })Provide default values for all configuration options:
tsconst config = await config<MyConfig>({ name: 'my-app', defaultConfig: { // Always provide defaults port: 3000, host: 'localhost', }, })Use TypeScript for configuration files when possible:
ts// my-app.config.ts (local) export default { port: 3000, host: 'localhost', } // ~/.config/my-app/config.ts (global) export default { port: 8080, host: 'production.example.com', }Use aliases for backward compatibility or alternative naming:
tsconst config = await config<MyConfig>({ name: 'new-name', alias: 'old-name', defaultConfig: { // ... }, })Use home directory configs for global settings that apply across projects:
ts// ~/.config/my-tool/config.ts - applies to all projects using 'my-tool' export default { globalSettings: true, defaultTheme: 'dark', }Use local configs for project-specific overrides:
ts// ./my-tool.config.ts - overrides global settings for this project export default { defaultTheme: 'light', // Override global setting projectSpecific: true, }