@boost/config
Version:
Powerful convention based finder, loader, and manager of both configuration and ignore files.
196 lines (178 loc) • 5.3 kB
JavaScript
import { Contract } from '@boost/common';
import { schemas } from '@boost/common/optimal';
import { WaterfallEvent, Event } from '@boost/event';
import { Cache } from './Cache.mjs';
import { ConfigFinder } from './ConfigFinder.mjs';
import { IgnoreFinder } from './IgnoreFinder.mjs';
import { Processor } from './Processor.mjs';
class Configuration extends Contract {
constructor(name, resolver) {
super();
/**
* Called after config files are loaded but before processed. Can modify config file list.
* @category Events
*/
this.onLoadedConfig = new WaterfallEvent('loaded-config');
/**
* Called after ignore files are loaded. Can modify ignore file list.
* @category Events
*/
this.onLoadedIgnore = new WaterfallEvent('loaded-ignore');
/**
* Called after config files are loaded and processed.
* @category Events
*/
this.onProcessedConfig = new Event('processed-config');
this.cache = void 0;
this.configFinder = void 0;
this.ignoreFinder = void 0;
this.processor = void 0;
this.cache = new Cache();
this.configFinder = new ConfigFinder({
name,
resolver
}, this.cache);
this.ignoreFinder = new IgnoreFinder({
name
}, this.cache);
this.processor = new Processor({
name
});
this.bootstrap();
}
/**
* Clear all cache.
*/
clearCache() {
this.clearFileCache();
this.clearFinderCache();
return this;
}
/**
* Clear all cached file contents.
*/
clearFileCache() {
this.cache.clearFileCache();
return this;
}
/**
* Clear all cached directory and file path information.
*/
clearFinderCache() {
this.cache.clearFinderCache();
return this;
}
/**
* Attempt to find the root directory starting from the provided directory.
* Once the root is found, it will be cached for further lookups,
* otherwise an error is thrown based on current configuration.
*/
async findRootDir(fromDir = process.cwd()) {
return this.getConfigFinder().findRootDir(fromDir);
}
/**
* Traverse upwards from the branch directory, until the root directory is found,
* or we reach to top of the file system. While traversing, find all config files
* within each branch directory, and the root.
*/
async loadConfigFromBranchToRoot(dir) {
const configs = await this.getConfigFinder().loadFromBranchToRoot(dir);
return this.processConfigs(this.onLoadedConfig.emit(configs));
}
/**
* Load config files from the defined root. Root is determined by a relative
* `.config` folder and `package.json` file.
*/
async loadConfigFromRoot(fromDir = process.cwd()) {
const configs = await this.getConfigFinder().loadFromRoot(fromDir);
return this.processConfigs(this.onLoadedConfig.emit(configs));
}
/**
* Traverse upwards from the branch directory, until the root directory is found,
* or we reach to top of the file system. While traversing, find all ignore files
* within each branch directory, and the root.
*/
async loadIgnoreFromBranchToRoot(dir) {
const ignores = await this.getIgnoreFinder().loadFromBranchToRoot(dir);
return this.onLoadedIgnore.emit(ignores);
}
/**
* Load ignore file from the defined root. Root is determined by a relative
* `.config` folder and `package.json` file.
*/
async loadIgnoreFromRoot(dir = process.cwd()) {
const ignores = await this.getIgnoreFinder().loadFromRoot(dir);
return this.onLoadedIgnore.emit(ignores);
}
/**
* Explicitly set the root directory to stop traversal at. This should only be set
* manually when you want full control, and know file boundaries up front.
*
* This *does not* check for the existence of the root config file or folder.
*/
setRootDir(dir) {
this.cache.setRootDir(dir);
return this;
}
/**
* Add a process handler to customize the processing of key-value setting pairs.
* May only run a processor on settings found in the root of the configuration object.
* @public
*/
addProcessHandler(key, handler) {
this.getProcessor().addHandler(key, handler);
return this;
}
/**
* Life cycle called on initialization.
* @public
*/
bootstrap() {}
/**
* Configure the finder instance.
* @public
*/
configureFinder(options) {
this.getConfigFinder().configure(options);
return this;
}
/**
* Configure the processor instance.
* @public
*/
configureProcessor(options) {
this.getProcessor().configure(options);
return this;
}
/**
* Return the config file finder instance.
*/
getConfigFinder() {
return this.configFinder;
}
/**
* Return the ignore file finder instance.
*/
getIgnoreFinder() {
return this.ignoreFinder;
}
/**
* Return the processor instance.
*/
getProcessor() {
return this.processor;
}
/**
* Process all loaded config objects into a single config object, and then validate.
*/
async processConfigs(files) {
const config = await this.getProcessor().process(this.options, files, this.blueprint(schemas));
this.onProcessedConfig.emit([config]);
return {
config,
files
};
}
}
export { Configuration };
//# sourceMappingURL=Configuration.mjs.map