config.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. 'use strict';
  2. /**
  3. * Responsible for loading / finding Mocha's "rc" files.
  4. *
  5. * @private
  6. * @module
  7. */
  8. const fs = require('node:fs');
  9. const path = require('node:path');
  10. const debug = require('debug')('mocha:cli:config');
  11. const findUp = require('find-up');
  12. const {createUnparsableFileError} = require('../errors');
  13. const utils = require('../utils');
  14. /**
  15. * These are the valid config files, in order of precedence;
  16. * e.g., if `.mocharc.js` is present, then `.mocharc.yaml` and the rest
  17. * will be ignored.
  18. * The user should still be able to explicitly specify a file.
  19. * @private
  20. */
  21. exports.CONFIG_FILES = [
  22. '.mocharc.cjs',
  23. '.mocharc.js',
  24. '.mocharc.yaml',
  25. '.mocharc.yml',
  26. '.mocharc.jsonc',
  27. '.mocharc.json'
  28. ];
  29. /**
  30. * Parsers for various config filetypes. Each accepts a filepath and
  31. * returns an object (but could throw)
  32. */
  33. const parsers = (exports.parsers = {
  34. yaml: filepath => require('js-yaml').load(fs.readFileSync(filepath, 'utf8')),
  35. js: filepath => {
  36. let cwdFilepath;
  37. try {
  38. debug('parsers: load cwd-relative path: "%s"', path.resolve(filepath));
  39. cwdFilepath = require.resolve(path.resolve(filepath)); // evtl. throws
  40. return require(cwdFilepath);
  41. } catch (err) {
  42. if (cwdFilepath) throw err;
  43. debug('parsers: retry load as module-relative path: "%s"', filepath);
  44. return require(filepath);
  45. }
  46. },
  47. json: filepath =>
  48. JSON.parse(
  49. require('strip-json-comments')(fs.readFileSync(filepath, 'utf8'))
  50. )
  51. });
  52. /**
  53. * Loads and parses, based on file extension, a config file.
  54. * "JSON" files may have comments.
  55. *
  56. * @private
  57. * @param {string} filepath - Config file path to load
  58. * @returns {Object} Parsed config object
  59. */
  60. exports.loadConfig = filepath => {
  61. let config = {};
  62. debug('loadConfig: trying to parse config at %s', filepath);
  63. const ext = path.extname(filepath);
  64. try {
  65. if (ext === '.yml' || ext === '.yaml') {
  66. config = parsers.yaml(filepath);
  67. } else if (ext === '.js' || ext === '.cjs') {
  68. config = parsers.js(filepath);
  69. } else {
  70. config = parsers.json(filepath);
  71. }
  72. } catch (err) {
  73. throw createUnparsableFileError(
  74. `Unable to read/parse ${filepath}: ${err}`,
  75. filepath
  76. );
  77. }
  78. return config;
  79. };
  80. /**
  81. * Find ("find up") config file starting at `cwd`
  82. *
  83. * @param {string} [cwd] - Current working directory
  84. * @returns {string|null} Filepath to config, if found
  85. */
  86. exports.findConfig = (cwd = utils.cwd()) => {
  87. const filepath = findUp.sync(exports.CONFIG_FILES, {cwd});
  88. if (filepath) {
  89. debug('findConfig: found config file %s', filepath);
  90. }
  91. return filepath;
  92. };