UNPKG

3.44 kBJavaScriptView Raw
1/*
2 Copyright © 2018 Andrew Powell
3
4 This Source Code Form is subject to the terms of the Mozilla Public
5 License, v. 2.0. If a copy of the MPL was not distributed with this
6 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8 The above copyright notice and this permission notice shall be
9 included in all copies or substantial portions of this Source Code Form.
10*/
11const { existsSync } = require('fs');
12const { resolve } = require('path');
13
14const rechoir = require('rechoir');
15
16const { apply } = require('./plugin');
17
18const 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};
30const configTypes = {
31 function: (c, argv) => Promise.resolve(c(argv.env || {}, argv)),
32 object: (c) => Promise.resolve(c)
33};
34const cwd = process.cwd();
35const defaultConfigPath = resolve(cwd, 'webpack.config.js');
36
37const 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
56const loadConfig = async (argv) => {
57 if (!argv.config && existsSync(defaultConfigPath)) {
58 // eslint-disable-next-line no-param-reassign
59 argv.config = defaultConfigPath;
60 }
61
62 // let's not process any config if the user hasn't specified any
63 if (argv.config) {
64 const configName = typeof argv.config !== 'string' ? Object.keys(argv.config)[0] : null;
65 // e.g. --config.batman webpack.config.js
66 const configPath = argv.config[configName] || argv.config;
67 const resolvedPath = resolve(configPath);
68
69 // only register a loader if the config file extension matches one we support
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); // eslint-disable-line global-require, import/no-dynamic-require
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
109module.exports = { loadConfig };