Spaces:
Sleeping
Sleeping
| ; | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const {promisify} = require('util'); | |
| const camelcase = require('camelcase'); | |
| const findUp = require('find-up'); | |
| const resolveFrom = require('resolve-from'); | |
| const getPackageType = require('get-package-type'); | |
| const readFile = promisify(fs.readFile); | |
| let loadActive = false; | |
| function isLoading() { | |
| return loadActive; | |
| } | |
| const standardConfigFiles = [ | |
| '.nycrc', | |
| '.nycrc.json', | |
| '.nycrc.yml', | |
| '.nycrc.yaml', | |
| 'nyc.config.js', | |
| 'nyc.config.cjs', | |
| 'nyc.config.mjs' | |
| ]; | |
| function camelcasedConfig(config) { | |
| const results = {}; | |
| for (const [field, value] of Object.entries(config)) { | |
| results[camelcase(field)] = value; | |
| } | |
| return results; | |
| } | |
| async function findPackage(options) { | |
| const cwd = options.cwd || process.env.NYC_CWD || process.cwd(); | |
| const pkgPath = await findUp('package.json', {cwd}); | |
| if (pkgPath) { | |
| const pkgConfig = JSON.parse(await readFile(pkgPath, 'utf8')).nyc || {}; | |
| if ('cwd' in pkgConfig) { | |
| pkgConfig.cwd = path.resolve(path.dirname(pkgPath), pkgConfig.cwd); | |
| } | |
| return { | |
| cwd: path.dirname(pkgPath), | |
| pkgConfig | |
| }; | |
| } | |
| return { | |
| cwd, | |
| pkgConfig: {} | |
| }; | |
| } | |
| async function actualLoad(configFile) { | |
| if (!configFile) { | |
| return {}; | |
| } | |
| const configExt = path.extname(configFile).toLowerCase(); | |
| switch (configExt) { | |
| case '.js': | |
| /* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */ | |
| if (await getPackageType(configFile) === 'module') { | |
| return require('./load-esm')(configFile); | |
| } | |
| /* fallthrough */ | |
| case '.cjs': | |
| return require(configFile); | |
| /* istanbul ignore next: coverage for 13.2.0+ is shown in load-esm.js */ | |
| case '.mjs': | |
| return require('./load-esm')(configFile); | |
| case '.yml': | |
| case '.yaml': | |
| return require('js-yaml').load(await readFile(configFile, 'utf8')); | |
| default: | |
| return JSON.parse(await readFile(configFile, 'utf8')); | |
| } | |
| } | |
| async function loadFile(configFile) { | |
| /* This lets @istanbuljs/esm-loader-hook avoid circular initialization when loading | |
| * configuration. This should generally only happen when the loader hook is active | |
| * on the main nyc process. */ | |
| loadActive = true; | |
| try { | |
| return await actualLoad(configFile); | |
| } finally { | |
| loadActive = false; | |
| } | |
| } | |
| async function applyExtends(config, filename, loopCheck = new Set()) { | |
| config = camelcasedConfig(config); | |
| if ('extends' in config) { | |
| const extConfigs = [].concat(config.extends); | |
| if (extConfigs.some(e => typeof e !== 'string')) { | |
| throw new TypeError(`${filename} contains an invalid 'extends' option`); | |
| } | |
| delete config.extends; | |
| const filePath = path.dirname(filename); | |
| for (const extConfig of extConfigs) { | |
| const configFile = resolveFrom.silent(filePath, extConfig) || | |
| resolveFrom.silent(filePath, './' + extConfig); | |
| if (!configFile) { | |
| throw new Error(`Could not resolve configuration file ${extConfig} from ${path.dirname(filename)}.`); | |
| } | |
| if (loopCheck.has(configFile)) { | |
| throw new Error(`Circular extended configurations: '${configFile}'.`); | |
| } | |
| loopCheck.add(configFile); | |
| // eslint-disable-next-line no-await-in-loop | |
| const configLoaded = await loadFile(configFile); | |
| if ('cwd' in configLoaded) { | |
| configLoaded.cwd = path.resolve(path.dirname(configFile), configLoaded.cwd); | |
| } | |
| Object.assign( | |
| config, | |
| // eslint-disable-next-line no-await-in-loop | |
| await applyExtends(configLoaded, configFile, loopCheck) | |
| ); | |
| } | |
| } | |
| return config; | |
| } | |
| async function loadNycConfig(options = {}) { | |
| const {cwd, pkgConfig} = await findPackage(options); | |
| const configFiles = [].concat(options.nycrcPath || standardConfigFiles); | |
| const configFile = await findUp(configFiles, {cwd}); | |
| if (options.nycrcPath && !configFile) { | |
| throw new Error(`Requested configuration file ${options.nycrcPath} not found`); | |
| } | |
| const config = { | |
| cwd, | |
| ...(await applyExtends(pkgConfig, path.join(cwd, 'package.json'))), | |
| ...(await applyExtends(await loadFile(configFile), configFile)) | |
| }; | |
| const arrayFields = ['require', 'extension', 'exclude', 'include']; | |
| for (const arrayField of arrayFields) { | |
| if (config[arrayField]) { | |
| config[arrayField] = [].concat(config[arrayField]); | |
| } | |
| } | |
| return config; | |
| } | |
| module.exports = { | |
| loadNycConfig, | |
| isLoading | |
| }; | |