A config loading utility for the Rstack ecosystem, designed for loading JavaScript and TypeScript config files for projects like Rspack and Rsbuild.
# pnpm
pnpm add @rstackjs/load-config -D
# yarn
yarn add @rstackjs/load-config -D
# npm
npm add @rstackjs/load-config -D
# bun
bun add @rstackjs/load-config -Djiti is an optional peer dependency. Install it only when you use the jiti or auto loaders:
# pnpm
pnpm add jiti -D
# yarn
yarn add jiti -D
# npm
npm add jiti -D
# bun
bun add jiti -Dimport { loadConfig } from '@rstackjs/load-config';
const result = await loadConfig<{ name: string }>({
cwd: process.cwd(),
configFileNames: ['my-tool.config.ts', 'my-tool.config.mjs'],
});
console.log(result.content);
console.log(result.filePath);Given a config file:
// my-tool.config.ts
export default {
name: 'my-tool',
};loadConfig returns:
type LoadConfigResult<Config = unknown> = {
content: Config;
filePath: string | null;
dependencies: string[];
};If no config file is found, content is an empty object, filePath is null, and dependencies is an empty array.
Default object export:
export default {
name: 'my-tool',
};Function export:
export default ({ mode }) => {
return { mode };
};Async function export:
export default async ({ mode }) => {
return { mode };
};function loadConfig<Config = unknown, Params extends unknown[] = []>(
options?: LoadConfigOptions<Params>,
): Promise<LoadConfigResult<Config>>;The root directory used to resolve config files.
- Type:
string - Default:
process.cwd()
A relative or absolute path to a specific config file.
- Type:
string - Default:
undefined
When path is provided, the file must exist. Relative paths are resolved from cwd.
await loadConfig({
path: path.join(import.meta.dirname, 'custom.config.ts'),
});A list of file names to search in cwd when path is not provided.
- Type:
string[] - Default:
[]
await loadConfig({
configFileNames: [
'tool.config.ts',
'tool.config.mts',
'tool.config.js',
'tool.config.mjs',
],
});Controls how the config file is loaded.
- Type:
'auto' | 'jiti' | 'native' - Default:
'auto'
auto uses the native loader when possible and falls back to jiti.
JavaScript config files (.js, .mjs, .cjs) are always attempted with native dynamic import first; if native import fails and loader is not native, they fall back to jiti.
TypeScript config files use the native loader in runtimes with TypeScript support, Bun, or Deno; otherwise they use jiti.
Set loader to native to disable the jiti fallback.
await loadConfig({
path: 'tool.config.ts',
loader: 'native',
});The export to read from the config module.
- Type:
string | false - Default:
'default'
Use a string to read a named export:
// tool.config.ts
export const config = {
name: 'my-tool',
};await loadConfig({
path: 'tool.config.ts',
exportName: 'config',
});Set exportName to false to execute the config file without reading exports. The returned content is an empty object.
Arguments passed to a function config export.
- Type:
Params - Default:
[]
// tool.config.ts
export default ({ mode }: { mode: string }) => ({
mode,
});const result = await loadConfig<{ mode: string }, [{ mode: string }]>({
path: 'tool.config.ts',
configParams: [{ mode: 'production' }],
});Config functions may be async, but they must return a config object.
Bypasses module cache when loading the config.
- Type:
boolean - Default:
false
await loadConfig({
path: 'tool.config.mjs',
fresh: true,
});When using the native loader and fresh is enabled, dependencies contains absolute paths for files imported by the config file.
Preserve the original config path and dependencies when loading through an adapter:
import { withConfigMeta } from '@rstackjs/load-config';
const config = { name: 'my-tool' };
export default withConfigMeta(config, {
filePath: '/project/project.config.ts',
dependencies: ['/project/shared.ts'],
});loadConfig uses the supplied filePath and merges dependencies with the adapter file and its collected dependencies, removing duplicates.
- Use absolute paths.
filePath: nullmeans no underlying config was found;dependenciesis optional. - The helper modifies and returns the original config object. Repeated calls replace its metadata. Frozen or non-extensible objects are not supported.
- Call it on the final config object: object spread and JSON serialization discard the metadata.
MIT.