All files / src index.ts

100% Statements 33/33
96.87% Branches 31/32
100% Functions 2/2
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                                  3x                                     3x   3x                             41x 41x                           41x 41x 41x     41x 41x 35x 35x 35x 4x 4x 31x 31x 31x   6x 3x 3x 3x     41x 35x 34x 2x     38x 2x   36x 33x   3x   1x          
import fs from 'fs';
import path from 'path';
import mergeFun from 'lodash.merge';
import { jsLoader, LoadConfOption } from './loader/js';
import { jsonLoader } from './loader/json';
import { yamlLoader } from './loader/yaml';
import { tomlLoader } from './loader/toml';
import { iniLoader } from './loader/ini';
import { findConfigFile } from './utils';
 
export * from './utils';
export * from './loader/js';
export * from './loader/json';
export * from './loader/yaml';
export * from './loader/toml';
export * from './loader/ini';
 
export const merge = mergeFun;
 
export type LoaderFunc<T> = (filepath: string, content: string, jsOption?: LoadConfOption) => 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;
}
 
let configPath = '';
 
export const getConfigPath = () => configPath;
 
/**
 * 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 function autoConf<T>(namespace: string = 'autoconf', option: AutoConfOption<T> = {}) {
  const {
    searchPlaces = [],
    default: defaultValue = {},
    cwd = process.cwd(),
    ignoreLog = false,
    mustExist = ignoreLog || false,
    jsOption,
  } = option;
  const loaders: Loader<T> = {
    '.yml': yamlLoader,
    '.yaml': yamlLoader,
    '.ini': iniLoader,
    '.toml': tomlLoader,
    '.json': jsonLoader,
    '.json5': jsonLoader,
    '.jsonc': jsonLoader,
    '.js': jsLoader,
    '.ts': jsLoader,
    '.cjs': jsLoader,
    '.mjs': jsLoader,
    ...(option.loaders || {}),
  };
  const pkgPath = path.resolve(cwd, 'package.json');
  configPath = findConfigFile(namespace, cwd, searchPlaces);
  let content = '';
  let resultData: T;
  let loaderFunc: LoaderFunc<T>;
  try {
    if (configPath) {
      const extname = path.extname(configPath);
      const basename = path.basename(configPath);
      if (new RegExp(`^(.?${namespace}rc)$`).test(basename)) {
        content = fs.readFileSync(configPath, 'utf-8');
        loaderFunc = loaders['.json'];
      } else Eif (loaders[extname]) {
        content = fs.readFileSync(configPath, 'utf-8');
        loaderFunc = loaders[extname];
      }
    } else if (fs.existsSync(pkgPath)) {
      content = fs.readFileSync(pkgPath, 'utf-8');
      const result = loaders['.json'](configPath, content);
      resultData = (result as Record<string, T>)[namespace];
    }
 
    if (content && loaderFunc) {
      resultData = loaderFunc(configPath, content, jsOption);
      if (typeof resultData === 'function') {
        return merge(defaultValue, resultData, { default: resultData });
      }
    }
    if (!!mustExist && !configPath && !resultData) {
      return null;
    }
    if (resultData) {
      return merge(defaultValue, resultData);
    }
    console.log(`AUTO_CONF:ERROR: \x1b[31;1mCan't find config file\x1b[0m`);
  } catch (error) {
    console.log(`AUTO_CONF:CATCH:ERROR: \x1b[31;1m${error}\x1b[0m`);
  }
}
 
export default autoConf;