1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const { existsSync } = require('fs');
|
12 | const { resolve } = require('path');
|
13 |
|
14 | const rechoir = require('rechoir');
|
15 |
|
16 | const { apply } = require('./plugin');
|
17 |
|
18 | const fileTypes = {
|
19 | '.babel.js': ['@babel/register', 'babel-register', 'babel-core/register', 'babel/register'],
|
20 | '.babel.ts': ['@babel/register'],
|
21 | '.es6': ['@babel/register'],
|
22 | '.mjs': ['@babel/register'],
|
23 | '.ts': [
|
24 | 'ts-node/register',
|
25 | 'typescript-node/register',
|
26 | 'typescript-register',
|
27 | 'typescript-require'
|
28 | ]
|
29 | };
|
30 | const configTypes = {
|
31 | function: (c, argv) => Promise.resolve(c(argv.env || {}, argv)),
|
32 | object: (c) => Promise.resolve(c)
|
33 | };
|
34 | const cwd = process.cwd();
|
35 | const defaultConfigPath = resolve(cwd, 'webpack.config.js');
|
36 |
|
37 | const requireLoader = (extension) => {
|
38 | try {
|
39 | rechoir.prepare(fileTypes, `config${extension}`, cwd);
|
40 | } catch (e) {
|
41 | let message;
|
42 | if (/no module loader/i.test(e.message)) {
|
43 | const [, fileType] = e.message.match(/(".+").$/);
|
44 | message = `A loader could not be found for the ${fileType} file type`;
|
45 | } else {
|
46 | const modules = e.failures.map(({ moduleName }) => `\n ${moduleName}`);
|
47 | message = `${e.message.slice(0, -1)}:${modules}`;
|
48 | }
|
49 |
|
50 | const error = new RangeError(message);
|
51 | error.code = 'ERR_MODULE_LOADER';
|
52 | throw error;
|
53 | }
|
54 | };
|
55 |
|
56 | const loadConfig = async (argv) => {
|
57 | if (!argv.config && existsSync(defaultConfigPath)) {
|
58 |
|
59 | argv.config = defaultConfigPath;
|
60 | }
|
61 |
|
62 |
|
63 | if (argv.config) {
|
64 | const configName = typeof argv.config !== 'string' ? Object.keys(argv.config)[0] : null;
|
65 |
|
66 | const configPath = argv.config[configName] || argv.config;
|
67 | const resolvedPath = resolve(configPath);
|
68 |
|
69 |
|
70 | const extension = Object.keys(fileTypes).find((t) => resolvedPath.endsWith(t));
|
71 |
|
72 | if (extension) {
|
73 | requireLoader(extension);
|
74 | }
|
75 |
|
76 | let configExport = require(resolvedPath);
|
77 |
|
78 | if (configExport.default) {
|
79 | configExport = configExport.default;
|
80 | }
|
81 |
|
82 | if (configName) {
|
83 | if (!Array.isArray(configExport)) {
|
84 | throw new TypeError(
|
85 | `A config with name was specified, but the config ${configPath} does not export an Array.`
|
86 | );
|
87 | }
|
88 |
|
89 | configExport = configExport.find((c) => c.name === configName);
|
90 |
|
91 | if (!configExport) {
|
92 | throw new RangeError(`A config with name '${configName}' was not found in ${configPath}`);
|
93 | }
|
94 | }
|
95 |
|
96 | const configType = typeof configExport;
|
97 | let config = await configTypes[configType](configExport, argv);
|
98 | config = await apply(config, argv, resolvedPath);
|
99 |
|
100 | const watchConfig = [].concat(config).find((c) => !!c.watch);
|
101 | const result = { config, watchConfig };
|
102 |
|
103 | return result;
|
104 | }
|
105 |
|
106 | return { config: await apply({}, argv, process.cwd()) };
|
107 | };
|
108 |
|
109 | module.exports = { loadConfig };
|