UNPKG

5.91 kBJavaScriptView Raw
1'use strict';
2
3/* eslint-disable no-console */
4
5const fs = require('fs');
6const path = require('path');
7const findup = require('findup');
8const semverUtils = require('semver-utils');
9const prettyjson = require('prettyjson');
10const merge = require('lodash/merge');
11const isFinite = require('lodash/isFinite');
12const isUndefined = require('lodash/isUndefined');
13const utils = require('./utils/utils');
14const consts = require('./consts');
15const DvhbWebpackError = require('./utils/error');
16
17const CONFIG_FILENAME = 'dvhb.config.js';
18const DEFAULT_CONFIG = {
19 title: 'Dvhb Webpack Starter kit',
20 sourceDir: 'src',
21 assetsDir: null,
22 distDir: 'dist',
23 viewsDir: 'src/views',
24 template: 'src/index.html',
25 serverHost: 'localhost',
26 serverPort: 3000,
27 verbose: false,
28 extendWebpackConfig: null
29};
30const DEPENDENCIES = [
31 {
32 package: 'babel-core',
33 name: 'Babel',
34 from: 6,
35 to: 6,
36 },
37 {
38 package: 'webpack',
39 name: 'Webpack',
40 from: 1,
41 to: 2,
42 },
43];
44
45/**
46 * Read, parse and validate config file or passed config.
47 *
48 * @param {object} [options] CLI options (e.g. {verbose: true} or {config: 'filename'}) or all config options.
49 * @returns {object}
50 */
51function getConfig(options) {
52 options = options || {};
53
54 let configFilepath;
55 let config;
56
57 // Read config options from a file
58 configFilepath = findConfig(options.config);
59 config = require(configFilepath);
60
61 validateConfig(config);
62
63 const configDir = configFilepath ? path.dirname(configFilepath) : process.cwd();
64
65 validateDependencies(configDir);
66
67 let assetsDir = config.assetsDir;
68 if (assetsDir) {
69 assetsDir = path.resolve(configDir, assetsDir);
70 if (!utils.isDirectoryExists(assetsDir)) {
71 throw new DvhbWebpackError('DvhbWebpack: "assetsRoot" directory not found: ' + assetsDir);
72 }
73 }
74
75 config = merge({}, DEFAULT_CONFIG, config);
76 config = merge({}, config, {
77 env: options.env || 'development',
78 verbose: !!options.verbose,
79 sourceDir: path.resolve(configDir, config.sourceDir),
80 distDir: path.resolve(configDir, config.distDir),
81 viewsDir: path.resolve(configDir, config.viewsDir),
82 configDir,
83 assetsDir
84 });
85
86 if (config.template){
87 config.template = path.resolve(configDir, config.template)
88 }
89
90 if (config.verbose) {
91 console.log();
92 console.log('Using config file:', configFilepath);
93 console.log(prettyjson.render(config));
94 console.log();
95 }
96
97 return config;
98}
99
100/**
101 * Find config file: use file specified in the command line or try to find up the file tree.
102 *
103 * @param {Object} [file] File name.
104 * @return {string} Config absolute file path.
105 */
106function findConfig(file) {
107 if (file) {
108 // Custom config location
109
110 const configFilepath = file[0] === '/' ? file : path.join(process.cwd(), file);
111 if (!fs.existsSync(configFilepath)) {
112 throw new DvhbWebpackError('DvhbWebpack config not found: ' + configFilepath + '.');
113 }
114
115 return configFilepath;
116 }
117
118 // Search config file in all parent directories
119
120 let configDir;
121 try {
122 configDir = findup.sync(__dirname, CONFIG_FILENAME);
123 }
124 catch (exception) {
125 throw new DvhbWebpackError('DvhbWebpack config not found: ' + CONFIG_FILENAME + '.');
126 }
127
128 return path.join(configDir, CONFIG_FILENAME);
129}
130
131/**
132 * Validate config.
133 *
134 * @param {Object} config Config options.
135 */
136function validateConfig(config) {
137 if (config.extendWebpackConfig && typeof config.extendWebpackConfig !== 'function') {
138 throw new DvhbWebpackError('DvhbWebpack: "extendWebpackConfig" option must be a function.');
139 }
140}
141
142/**
143 * Validate project’s Babel and Webpack versions.
144 *
145 * @param {string} configDir Config file directory.
146 */
147function validateDependencies(configDir) {
148 const packageJsonPath = path.join(findup.sync(configDir, 'package.json'), 'package.json');
149 const packageJson = require(packageJsonPath);
150 DEPENDENCIES.forEach(validateDependency.bind(null, packageJson));
151}
152
153/**
154 * Check versions of a project dependency.
155 *
156 * @param {Object} packageJson package.json.
157 * @param {Object} dependency Dependency details.
158 */
159function validateDependency(packageJson, dependency) {
160 const version = findDependency(dependency.package, packageJson);
161 if (!version) {
162 return;
163 }
164
165 let major;
166 try {
167 major = semverUtils.parseRange(version)[0].major;
168 }
169 catch (exception) {
170 console.log('DvhbWebpack: cannot parse ' + dependency.name + ' version which is "' + version + '".');
171 console.log('DvhbWebpack might not work properly. Please report this issue at ' + consts.BUGS_URL);
172 console.log();
173 }
174
175 if (major < dependency.from) {
176 throw new DvhbWebpackError('DvhbWebpack: ' + dependency.name + ' ' + dependency.from + ' is required, ' +
177 'you are using version ' + major + '.');
178 }
179 else if (major > dependency.to) {
180 console.log('DvhbWebpack: ' + dependency.name + ' is supported up to version ' + dependency.to + ', ' +
181 'you are using version ' + major + '.');
182 console.log('DvhbWebpack might not work properly, report bugs at ' + consts.BUGS_URL);
183 console.log();
184 }
185}
186
187/**
188 * Find package in project’s dependencies or devDependencies.
189 *
190 * @param {string} name Package name.
191 * @param {Object} packageJson package.json.
192 * @returns {string}
193 */
194function findDependency(name, packageJson) {
195 if (packageJson.dependencies && packageJson.dependencies[name]) {
196 return packageJson.dependencies[name];
197 }
198 if (packageJson.devDependencies && packageJson.devDependencies[name]) {
199 return packageJson.devDependencies[name];
200 }
201 return null;
202}
203
204module.exports = getConfig;