auto-config-loader
Version:
Find and load configuration from a package.json property, rc file, or CommonJS module.
471 lines (369 loc) • 21.3 kB
Markdown
<div markdown="1">
<sup>Using <a href="https://wangchujiang.com/#/app" target="_blank">my app</a> is also a way to <a href="https://wangchujiang.com/#/sponsor" target="_blank">support</a> me:</sup>
<br>
<a target="_blank" href="https://apps.apple.com/app/Vidwall/6747587746" title="Vidwall for macOS"><img align="center" alt="Vidwall" height="52" width="52" src="https://github.com/user-attachments/assets/7b5df70a-ed91-4d4b-85be-f00e60a09ce9"></a>
<a target="_blank" href="https://wangchujiang.com/mousio-hint/" title="Mousio Hint for macOS"><img align="center" alt="Mousio Hint" height="52" width="52" src="https://github.com/user-attachments/assets/3c0af128-0cef-44e5-a8db-4741dc5a6690"></a>
<a target="_blank" href="https://apps.apple.com/app/6746747327" title="Mousio for macOS"><img align="center" alt="Mousio" height="52" width="52" src="https://github.com/user-attachments/assets/9edf61ff-5a6c-4676-9cc2-8fd3c1ad0dfb"></a>
<a target="_blank" href="https://apps.apple.com/app/6745227444" title="Musicer for macOS"><img align="center" alt="Musicer" height="52" width="52" src="https://github.com/user-attachments/assets/b7abfba8-88ff-4c86-a125-43073d5aef22"></a>
<a target="_blank" href="https://apps.apple.com/app/6743841447" title="Audioer for macOS"><img align="center" alt="Audioer" height="52" width="52" src="https://github.com/user-attachments/assets/7a836865-8c90-4119-87bc-19e06a76c957"></a>
<a target="_blank" href="https://apps.apple.com/app/6744690194" title="FileSentinel for macOS"><img align="center" alt="FileSentinel" height="52" width="52" src="https://github.com/user-attachments/assets/28bce2cc-290e-45bf-9068-585ff6ecafe9"></a>
<a target="_blank" href="https://apps.apple.com/app/6743495172" title="FocusCursor for macOS"><img align="center" alt="FocusCursor" height="52" width="52" src="https://github.com/user-attachments/assets/d543668a-737b-4853-a6bb-eaa269e69836"></a>
<a target="_blank" href="https://apps.apple.com/app/6742680573" title="Videoer for macOS"><img align="center" alt="Videoer" height="52" width="52" src="https://github.com/user-attachments/assets/10ffb0f1-0625-40d6-93f1-2c2496592595"></a>
<a target="_blank" href="https://apps.apple.com/app/6740425504" title="KeyClicker for macOS"><img align="center" alt="KeyClicker" height="52" width="52" src="https://github.com/user-attachments/assets/5a19fcb9-cb81-4855-b4ea-31c604d9612a"></a>
<a target="_blank" href="https://apps.apple.com/app/6739052447" title="DayBar for macOS"><img align="center" alt="DayBar" height="52" width="52" src="https://github.com/user-attachments/assets/771b608d-594c-492d-8532-d9231e383f5b"></a>
<a target="_blank" href="https://apps.apple.com/app/6739444407" title="Iconed for macOS"><img align="center" alt="Iconed" height="52" width="52" src="https://github.com/user-attachments/assets/8a35dc7b-4faf-4e2a-9311-f66d6844a896"></a>
<a target="_blank" href="https://apps.apple.com/app/6737160756" title="RightMenu Master for macOS"><img align="center" alt="RightMenu Master" height="52" width="52" src="https://github.com/user-attachments/assets/39a76541-71bf-4de7-a01c-c62f0557dff5"></a>
<a target="_blank" href="https://apps.apple.com/app/6723903021" title="Paste Quick for macOS"><img align="center" alt="Quick RSS" height="52" width="52" src="https://github.com/user-attachments/assets/bdaad5b7-9810-44ce-8f17-8410864465d2"></a>
<a target="_blank" href="https://apps.apple.com/app/6670696072" title="Quick RSS for macOS/iOS"><img align="center" alt="Quick RSS" height="52" width="52" src="https://github.com/user-attachments/assets/374106b5-a448-4d1d-9ccb-b04b6bc681ed"></a>
<a target="_blank" href="https://apps.apple.com/app/6670167443" title="Web Serve for macOS"><img align="center" alt="Web Serve" height="52" width="52" src="https://github.com/user-attachments/assets/e1d9f76f-0f3d-4ba5-8a15-253ee173bb1c"></a>
<a target="_blank" href="https://apps.apple.com/app/6503953628" title="Copybook Generator for macOS/iOS"><img align="center" alt="Copybook Generator" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/b90e42ff-158b-4534-82ca-5898fd0e8d73"></a>
<a target="_blank" href="https://apps.apple.com/app/6471227008" title="DevTutor for macOS/iOS"><img align="center" alt="DevTutor for SwiftUI" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/f15c154d-0192-48eb-8e0e-9e245ffd974a"></a>
<a target="_blank" href="https://apps.apple.com/app/6479819388" title="RegexMate for macOS/iOS"><img align="center" alt="RegexMate" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/aabe5aa9-9a96-4390-8bed-c3e4023d0dea"></a>
<a target="_blank" href="https://apps.apple.com/app/6479194014" title="Time Passage for macOS/iOS"><img align="center" alt="Time Passage" height="52" width="52" src="https://github.com/jaywcjlove/time-passage/assets/1680273/6f30e429-e6f3-4dbe-9921-a5effe2a05e9"></a>
<a target="_blank" href="https://apps.apple.com/app/6478772538" title="IconizeFolder for macOS"><img align="center" alt="Iconize Folder" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/fa9d8b9c-1e51-4ded-877c-fa5b21c47220"></a>
<a target="_blank" href="https://apps.apple.com/app/6478511402" title="Textsound Saver for macOS/iOS"><img align="center" alt="Textsound Saver" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/0595e842-980b-4574-8891-a8ba853a08be"></a>
<a target="_blank" href="https://apps.apple.com/app/6476924627" title="Create Custom Symbols for macOS"><img align="center" alt="Create Custom Symbols" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/8cd022ce-a3f1-4e89-b7c6-6fbd0d4db77c"></a>
<a target="_blank" href="https://apps.apple.com/app/6476452351" title="DevHub for macOS"><img align="center" alt="DevHub" height="52" width="52" src="https://github.com/user-attachments/assets/4a44a4fd-67ce-430b-af0a-72f18feaa47d"></a>
<a target="_blank" href="https://apps.apple.com/app/6476400184" title="Resume Revise for macOS"><img align="center" alt="Resume Revise" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/c9954a20-1905-48de-bdf8-d71837974aa2"></a>
<a target="_blank" href="https://apps.apple.com/app/6472593276" title="Palette Genius for macOS"><img align="center" alt="Palette Genius" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/27340413-d355-45b2-8f6f-6ac37682d957"></a>
<a target="_blank" href="https://apps.apple.com/app/6470879005" title="Symbol Scribe for macOS"><img align="center" alt="Symbol Scribe" height="52" width="52" src="https://github.com/jaywcjlove/jaywcjlove/assets/1680273/c7249f05-fa70-4def-a1e9-571d5f171fc9"></a>
</div>
<hr>
Auto Config Loader
===
[](https://jaywcjlove.github.io/#/sponsor)
[](https://github.com/jaywcjlove/auto-config-loader/actions/workflows/main.yml)
[](https://npmjs.org/package/auto-config-loader)
[](https://jaywcjlove.github.io/auto-config-loader/lcov-report/)
[](https://www.npmjs.com/package/auto-config-loader)
Find and load configuration from a `package.json` property, `rc` file, or `CommonJS` module. It has smart default based on traditional expectations in the JavaScript ecosystem. But it's also flexible enough to search anywhere you want and load whatever you want.
[V1 To V2 Migration](#v1-to-v2-migration)
## Features
- Support [JSON](https://www.json.org), [JSONC](https://github.com/microsoft/node-jsonc-parser), [JSON5](https://json5.org/), [YAML](https://yaml.org/), [TOML](https://toml.io), [INI](https://en.wikipedia.org/wiki/INI_file), [CJS](http://www.commonjs.org), [Typescript](https://www.typescriptlang.org/), and ESM config load.
- Reads config from the nearest `package.json` file
## Install
```bash
$ npm i auto-config-loader
```
## Quick start
```js
const autoConf = require('auto-config-loader');
import { autoConf } from 'auto-config-loader';
// will look for:
// process.cwd() + '.namespacerc'
// process.cwd() + '.namespacerc.js'
// process.cwd() + '.namespacerc.ts'
// process.cwd() + '.namespacerc.mjs'
// process.cwd() + '.namespacerc.cjs'
// process.cwd() + '.namespacerc.json'
// process.cwd() + '.namespacerc.json5'
// process.cwd() + '.namespacerc.jsonc'
// process.cwd() + '.namespacerc.yaml'
// process.cwd() + '.namespacerc.yml'
// process.cwd() + '.namespacerc.toml'
// process.cwd() + 'namespace.config.mjs'
// process.cwd() + 'namespace.config.cjs'
// process.cwd() + 'namespace.config.js'
// ........
const data = await autoConf('namespace', {
default: {
testItem2: 'some value'
}
});
```
## Load JS
Load the JS file and return the result, support `.js`, `.cjs`, `.mjs`, `.ts`.
```js
// => ./app/app.config.js
export default {
name: 'app'
}
```
```ts
import { loadConf } from 'auto-config-loader/load-conf';
interface Config {
name: string;
}
const result = await loadConf<Config>('./app/app.config.js');
// => { name: 'app' }
```
## Option
```ts
import { LoadConfOption } from 'auto-config-loader';
export type LoaderFunc<T> = (filepath: string, content: string, jsOption?: LoadConfOption) => T | Promise<T>;
export type Loader<T> = Record<string, LoaderFunc<T>>;
export interface AutoConfOption<T> {
searchPlaces?: string[];
/** An object that maps extensions to the loader functions responsible for loading and parsing files with those extensions. */
loaders?: Loader<T>;
/** Specify default configuration. It has the lowest priority and is applied after extending config. */
default?: T;
/** Resolve configuration from this working directory. The default is `process.cwd()` */
cwd?: string;
/** Default transform js configuration */
jsOption?: LoadConfOption;
/** @deprecated use `mustExist` instead */
ignoreLog?: boolean;
mustExist?: boolean;
}
export declare const getConfigPath: () => string;
/**
* Find and load configuration from a `package.json` property, `rc` file, or `CommonJS` module.
* @param namespace {string} Configuration base name. The default is `autoconf`.
* @param option
*/
export declare function autoConf<T>(namespace?: string, option?: AutoConfOption<T>): Promise<{} & T>;
export default autoConf;
```
Discover configurations in the specified directory order. When configuring a tool, you can use multiple file formats and put these in multiple places. Usually, a tool would mention this in its own README file, but by default, these are the following places, where `${moduleName}` represents the name of the tool:
**Default `searchPlaces`:**
```js
[
'package.json',
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.json5`,
`.${moduleName}rc.jsonc`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.${moduleName}rc.toml`,
`.${moduleName}rc.ini`,
`.${moduleName}rc.js`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.cjs`,
`.${moduleName}rc.mjs`,
`.config/${moduleName}rc`,
`.config/${moduleName}rc.json`,
`.config/${moduleName}rc.json5`,
`.config/${moduleName}rc.jsonc`,
`.config/${moduleName}rc.yaml`,
`.config/${moduleName}rc.yml`,
`.config/${moduleName}rc.toml`,
`.config/${moduleName}rc.ini`,
`.config/${moduleName}rc.js`,
`.config/${moduleName}rc.ts`,
`.config/${moduleName}rc.cjs`,
`.config/${moduleName}rc.mjs`,
`${moduleName}.config.js`,
`${moduleName}.config.ts`,
`${moduleName}.config.cjs`,
`${moduleName}.config.mjs`,
]
```
Configurations are loaded sequentially, and the configuration file search is terminated when a configuration file exists.
The content of these files is defined by the tool. For example, you can add a `semi` configuration value to `false` using a file called `.config/autoconfig.yml`:
```yml
semi: true
```
Additionally, you have the option to put a property named after the tool in your `package.json` file, with the contents of that property being the same as the file contents. To use the same example as above:
```js
{
"name": "your-project",
"autoconfig": {
"semi": true
}
}
```
This has the advantage that you can put the configuration of all tools (at least the ones that use `auto-config-loader`) in one file.
## Loader
### `.js`,`.ts`,`.cjs`,`.mjs`
```ts
import type jiti from 'jiti';
import { Options } from 'sucrase';
type Jiti = ReturnType<typeof jiti>;
type JITIOptions = Jiti['options'];
export interface LoadConfOption {
jiti?: boolean;
jitiOptions?: JITIOptions;
transformOption?: Options;
}
export declare function loadConf<T>(path: string, option?: LoadConfOption): Promise<T>;
export declare function jsLoader<T>(
filepath: string,
content: string,
option?: LoadConfOption
): Promise<T>;
```
Modify default `.js`,`.ts`,`.cjs`,`.mjs` loader parameters.
```js
import load, { jsLoader } from 'auto-config-loader';
function loadJS(filepath, content) {
return jsLoader(filepath, content, {
// change option...
});
}
const data = await load('namespace', {
loaders: {
'.js': loadJS,
'.ts': loadJS,
'.cjs': loadJS,
'.mjs': loadJS,
},
default: {
testItem2: 'some value'
}
});
```
example:
```ts
import { jsLoader } from 'auto-config-loader';
const data = jsLoader('/path/to/file/name.js')
```
### `.ini`
```ts
export declare function iniLoader<T>(_: string, content: string): T;
```
example:
```ts
import { iniLoader } from 'auto-config-loader';
const data = iniLoader(undefined, `...`)
```
### `.json`,`.jsonc`, `json5`
```ts
export declare function jsonLoader<T>(_: string, content: string): T;
```
example:
```ts
import { jsonLoader } from 'auto-config-loader';
const data = jsonLoader(undefined, `{ "a": 123 }`)
```
### `.toml`
```ts
export declare function tomlLoader<T>(_: string, content: string): T;
```
example:
```ts
import { tomlLoader } from 'auto-config-loader';
const data = tomlLoader(undefined, `...`)
```
### `.yaml`
```ts
export declare function yamlLoader<T>(_: string, content: string): T;
```
example:
```ts
import { yamlLoader } from 'auto-config-loader';
const data = yamlLoader(undefined, `...`)
```
## Custom `Yaml` loader
This is an example, the default `yaml`/`yml` does not require a loader.
```js
import load from 'auto-config-loader';
import yaml from 'yaml';
function loadYaml(filepath, content) {
return yaml.parse(content);
}
const data = await load('namespace', {
searchPlaces: [
'.namespacerc.yaml',
'.namespacerc.yml',
],
loaders: {
'.yaml': loadYaml,
'.yml': loadYaml,
},
default: {
testItem2: 'some value'
}
});
```
## Utils
### merge
```ts
export declare const merge: {
<TObject, TSource>(object: TObject, source: TSource): TObject & TSource;
<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2;
<TObject, TSource1, TSource2, TSource3>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3): TObject & TSource1 & TSource2 & TSource3;
<TObject, TSource1, TSource2, TSource3, TSource4>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3, source4: TSource4): TObject & TSource1 & TSource2 & TSource3 & TSource4;
(object: any, ...otherArgs: any[]): any;
};
```
### findConfigFile
```ts
export declare function findConfigFile(
moduleName: string,
root: string,
searchPlaces?: string[]
): string;
```
### getConfigPath
```ts
export declare const getConfigPath: () => string;
```
Example:
```ts
import { autoConf, getConfigPath } from 'auto-config-loader';
const data = autoConf<Config>('idoc');
const configPath = getConfigPath();
// => /.autoconfrc.js
```
## V1 To V2 Migration
This guide provides the steps to migrate to the latest version of the configuration loader API.
### Key Changes
1. **Loader Functions Support Async**
- `LoaderFunc<T>` now supports returning `T` or `Promise<T>`.
- Update custom loaders to handle asynchronous operations if needed.
**Example:**
```ts
export type LoaderFunc<T> = (
filepath: string,
content: string,
jsOption?: LoadConfOption
) => T | Promise<T>;
```
2. **`autoConf` Returns a Promise**
- The `autoConf` function now returns a `Promise` instead of a synchronous result.
- Update your code to handle asynchronous calls.
**Example:**
```ts
export declare function autoConf<T>(
namespace?: string,
option?: AutoConfOption<T>
): Promise<{} & T>;
```
### Migration Steps
#### 1. Update Custom Loader Functions
If you have custom loaders, update their return types to support asynchronous operations:
**Example:**
```ts
const jsonLoader: LoaderFunc<MyConfig> = async (
filepath, content
) => JSON.parse(content);
```
#### 2. Handle Asynchronous `autoConf` Calls
Update all calls to `autoConf` to use `await` or `.then` to handle Promises:
**Example Using `await`:**
```ts
const config = await autoConf('myNamespace', options);
console.log(config);
```
**Example Using `.then`:**
```ts
autoConf('myNamespace', options).then(config => {
console.log(config);
});
```
## Related
- [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig) Find and load configuration from a package.json property, rc file, or CommonJS module
- [cjson](https://www.npmjs.com/package/cjson) Comments enabled json loader (Commented JavaScript Object Notation)
- [Config Loader](https://www.npmjs.com/package/@web/config-loader) Load user config files for node js projects.
- [Lilconfig](https://www.npmjs.com/package/lilconfig) Zero-dependency nodejs config seeker.
- [proload](https://github.com/natemoo-re/proload) Searches for and loads your tool's JavaScript configuration files with full support for CJS, ESM, TypeScript and more.
- [rc](https://github.com/dominictarr/rc) The non-configurable configuration loader for lazy people.
Library | Last commit | Download | loaders | config ext
:-- | --- | --- | --- | ---
**auto-config-loader** | [](https://github.com/jaywcjlove/auto-config-loader/commits) | [](https://www.npmjs.com/package/auto-config-loader) | ✅ | `.js`, `.ts`, `.cjs`, `.mjs`, `.json`, `.jsonc`, `json5`, `.ini`, `.toml`, `.yaml` ++
cosmiconfig | [](https://github.com/cosmiconfig/cosmiconfig/commits) | [](https://www.npmjs.com/package/cosmiconfig) | ✅ | `.json`, `.yaml`, `.yml`, `.js`, `.mjs`, `.cjs`
~~rc~~ | [](https://github.com/dominictarr/rc/commits) | [](https://www.npmjs.com/package/rc) | ✅ | `.json`, `.yaml`, `.yml`, `.js`, `.mjs`, `.cjs`
/core | [](https://github.com/natemoo-re/proload/commits) | [](https://www.npmjs.com/package/@proload/core) | ✅ | `.js`, `.ts`, `.cjs`, `.mjs`, `.json`, `.jsonc`, `json5`, `.ini`, `.toml`, `.yaml` ++
lilconfig | [](https://github.com/antonk52/lilconfig/commits) | [](https://www.npmjs.com/package/lilconfig) | ✅ | `.js`, `.cjs`, `.mjs`, `.json` ++
~~cjson~~ | [](https://github.com/kof/node-cjson/commits) | [](https://www.npmjs.com/package/cjson) | ✅ | `.json`
/config-loader | [](https://github.com/modernweb-dev/web/commits) | [](https://www.npmjs.com/package/@web/config-loader) | ❌ | `.js`, `.mjs`, `.cjs`
## Contributors
As always, thanks to our amazing contributors!
<a href="https://github.com/jaywcjlove/auto-config-loader/graphs/contributors">
<img src="https://jaywcjlove.github.io/auto-config-loader/CONTRIBUTORS.svg" />
</a>
Made with [contributors](https://github.com/jaywcjlove/github-action-contributors).
## License
This package is licensed under the MIT License.