UNPKG

2.37 kBJavaScriptView Raw
1'use strict';
2const path = require('path');
3const esm = require('esm');
4const isPlainObject = require('is-plain-object');
5const pkgConf = require('pkg-conf');
6
7const NO_SUCH_FILE = Symbol('no ava.config.js file');
8const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
9
10function loadConfig(resolveFrom = process.cwd(), defaults = {}) {
11 const packageConf = pkgConf.sync('ava', {cwd: resolveFrom});
12 const filepath = pkgConf.filepath(packageConf);
13 const projectDir = filepath === null ? resolveFrom : path.dirname(filepath);
14
15 let fileConf;
16 try {
17 ({default: fileConf = MISSING_DEFAULT_EXPORT} = esm(module, {
18 cjs: {
19 cache: false,
20 extensions: false,
21 interop: false,
22 mutableNamespace: false,
23 namedExports: false,
24 paths: false,
25 vars: true
26 },
27 force: true,
28 mode: 'all'
29 })(path.join(projectDir, 'ava.config.js')));
30 } catch (error) {
31 if (error && error.code === 'MODULE_NOT_FOUND') {
32 fileConf = NO_SUCH_FILE;
33 } else {
34 throw Object.assign(new Error('Error loading ava.config.js'), {parent: error});
35 }
36 }
37
38 if (fileConf === MISSING_DEFAULT_EXPORT) {
39 throw new Error('ava.config.js must have a default export, using ES module syntax');
40 }
41
42 if (fileConf !== NO_SUCH_FILE) {
43 if (Object.keys(packageConf).length > 0) {
44 throw new Error('Conflicting configuration in ava.config.js and package.json');
45 }
46
47 if (fileConf && typeof fileConf.then === 'function') { // eslint-disable-line promise/prefer-await-to-then
48 throw new TypeError('ava.config.js must not export a promise');
49 }
50
51 if (!isPlainObject(fileConf) && typeof fileConf !== 'function') {
52 throw new TypeError('ava.config.js must export a plain object or factory function');
53 }
54
55 if (typeof fileConf === 'function') {
56 fileConf = fileConf({projectDir});
57 if (fileConf && typeof fileConf.then === 'function') { // eslint-disable-line promise/prefer-await-to-then
58 throw new TypeError('Factory method exported by ava.config.js must not return a promise');
59 }
60
61 if (!isPlainObject(fileConf)) {
62 throw new TypeError('Factory method exported by ava.config.js must return a plain object');
63 }
64 }
65
66 if ('ava' in fileConf) {
67 throw new Error('Encountered \'ava\' property in ava.config.js; avoid wrapping the configuration');
68 }
69 }
70
71 return {...defaults, ...fileConf, ...packageConf, projectDir};
72}
73
74module.exports = loadConfig;