| "use strict"; |
| |
| /** |
| * Responsible for loading / finding Mocha's "rc" files. |
| * |
| * @private |
| * @module |
| */ |
| |
| const fs = require("node:fs"); |
| const path = require("node:path"); |
| const debug = require("debug")("mocha:cli:config"); |
| const findUp = require("find-up"); |
| const { createUnparsableFileError } = require("../errors.js"); |
| const utils = require("../utils.cjs"); |
| |
| /** |
| * These are the valid config files, in order of precedence; |
| * e.g., if `.mocharc.js` is present, then `.mocharc.yaml` and the rest |
| * will be ignored. |
| * The user should still be able to explicitly specify a file. |
| * @private |
| */ |
| // This is documented publicly in `configuring.mdx` |
| exports.CONFIG_FILES = [ |
| ".mocharc.cjs", |
| ".mocharc.js", |
| ".mocharc.mjs", |
| ".mocharc.yaml", |
| ".mocharc.yml", |
| ".mocharc.jsonc", |
| ".mocharc.json", |
| ]; |
| |
| /** |
| * Parsers for various config filetypes. Each accepts a filepath and |
| * returns an object (but could throw) |
| */ |
| const parsers = (exports.parsers = { |
| yaml: (filepath) => |
| require("js-yaml").load(fs.readFileSync(filepath, "utf8")), |
| js: (filepath) => { |
| let cwdFilepath; |
| try { |
| debug('parsers: load cwd-relative path: "%s"', path.resolve(filepath)); |
| cwdFilepath = require.resolve(path.resolve(filepath)); // evtl. throws |
| return require(cwdFilepath); |
| } catch (err) { |
| if (cwdFilepath) throw err; |
| |
| debug('parsers: retry load as module-relative path: "%s"', filepath); |
| return require(filepath); |
| } |
| }, |
| json: (filepath) => |
| JSON.parse( |
| require("strip-json-comments").default(fs.readFileSync(filepath, "utf8")), |
| ), |
| }); |
| |
| /** |
| * Loads and parses, based on file extension, a config file. |
| * "JSON" files may have comments. |
| * |
| * @private |
| * @param {string} filepath - Config file path to load |
| * @returns {Object} Parsed config object |
| */ |
| exports.loadConfig = (filepath) => { |
| let config; |
| debug("loadConfig: trying to parse config at %s", filepath); |
| |
| const ext = path.extname(filepath); |
| try { |
| if (ext === ".yml" || ext === ".yaml") { |
| config = parsers.yaml(filepath); |
| } else if (ext === ".js" || ext === ".cjs" || ext === ".mjs") { |
| const parsedConfig = parsers.js(filepath); |
| config = parsedConfig.default ?? parsedConfig; |
| } else { |
| config = parsers.json(filepath); |
| } |
| } catch (err) { |
| throw createUnparsableFileError( |
| `Unable to read/parse ${filepath}: ${err}`, |
| filepath, |
| ); |
| } |
| return config; |
| }; |
| |
| /** |
| * Find ("find up") config file starting at `cwd` |
| * |
| * @param {string} [cwd] - Current working directory |
| * @returns {string|null} Filepath to config, if found |
| */ |
| exports.findConfig = (cwd = utils.cwd()) => { |
| const filepath = findUp.sync(exports.CONFIG_FILES, { cwd }); |
| if (filepath) { |
| debug("findConfig: found config file %s", filepath); |
| } |
| return filepath; |
| }; |