UNPKG

10 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.ROOT_CONFIG_FILENAMES = void 0;
7exports.findConfigUpwards = findConfigUpwards;
8exports.findRelativeConfig = findRelativeConfig;
9exports.findRootConfig = findRootConfig;
10exports.loadConfig = loadConfig;
11exports.resolveShowConfigPath = resolveShowConfigPath;
12
13function _debug() {
14 const data = require("debug");
15
16 _debug = function () {
17 return data;
18 };
19
20 return data;
21}
22
23function _fs() {
24 const data = require("fs");
25
26 _fs = function () {
27 return data;
28 };
29
30 return data;
31}
32
33function _path() {
34 const data = require("path");
35
36 _path = function () {
37 return data;
38 };
39
40 return data;
41}
42
43function _json() {
44 const data = require("json5");
45
46 _json = function () {
47 return data;
48 };
49
50 return data;
51}
52
53function _gensync() {
54 const data = require("gensync");
55
56 _gensync = function () {
57 return data;
58 };
59
60 return data;
61}
62
63var _caching = require("../caching");
64
65var _configApi = require("../helpers/config-api");
66
67var _utils = require("./utils");
68
69var _moduleTypes = require("./module-types");
70
71var _patternToRegex = require("../pattern-to-regex");
72
73var fs = require("../../gensync-utils/fs");
74
75function _module() {
76 const data = require("module");
77
78 _module = function () {
79 return data;
80 };
81
82 return data;
83}
84
85const debug = _debug()("babel:config:loading:files:configuration");
86
87const ROOT_CONFIG_FILENAMES = ["babel.config.js", "babel.config.cjs", "babel.config.mjs", "babel.config.json"];
88exports.ROOT_CONFIG_FILENAMES = ROOT_CONFIG_FILENAMES;
89const RELATIVE_CONFIG_FILENAMES = [".babelrc", ".babelrc.js", ".babelrc.cjs", ".babelrc.mjs", ".babelrc.json"];
90const BABELIGNORE_FILENAME = ".babelignore";
91
92function findConfigUpwards(rootDir) {
93 let dirname = rootDir;
94
95 for (;;) {
96 for (const filename of ROOT_CONFIG_FILENAMES) {
97 if (_fs().existsSync(_path().join(dirname, filename))) {
98 return dirname;
99 }
100 }
101
102 const nextDir = _path().dirname(dirname);
103
104 if (dirname === nextDir) break;
105 dirname = nextDir;
106 }
107
108 return null;
109}
110
111function* findRelativeConfig(packageData, envName, caller) {
112 let config = null;
113 let ignore = null;
114
115 const dirname = _path().dirname(packageData.filepath);
116
117 for (const loc of packageData.directories) {
118 if (!config) {
119 var _packageData$pkg;
120
121 config = yield* loadOneConfig(RELATIVE_CONFIG_FILENAMES, loc, envName, caller, ((_packageData$pkg = packageData.pkg) == null ? void 0 : _packageData$pkg.dirname) === loc ? packageToBabelConfig(packageData.pkg) : null);
122 }
123
124 if (!ignore) {
125 const ignoreLoc = _path().join(loc, BABELIGNORE_FILENAME);
126
127 ignore = yield* readIgnoreConfig(ignoreLoc);
128
129 if (ignore) {
130 debug("Found ignore %o from %o.", ignore.filepath, dirname);
131 }
132 }
133 }
134
135 return {
136 config,
137 ignore
138 };
139}
140
141function findRootConfig(dirname, envName, caller) {
142 return loadOneConfig(ROOT_CONFIG_FILENAMES, dirname, envName, caller);
143}
144
145function* loadOneConfig(names, dirname, envName, caller, previousConfig = null) {
146 const configs = yield* _gensync().all(names.map(filename => readConfig(_path().join(dirname, filename), envName, caller)));
147 const config = configs.reduce((previousConfig, config) => {
148 if (config && previousConfig) {
149 throw new Error(`Multiple configuration files found. Please remove one:\n` + ` - ${_path().basename(previousConfig.filepath)}\n` + ` - ${config.filepath}\n` + `from ${dirname}`);
150 }
151
152 return config || previousConfig;
153 }, previousConfig);
154
155 if (config) {
156 debug("Found configuration %o from %o.", config.filepath, dirname);
157 }
158
159 return config;
160}
161
162function* loadConfig(name, dirname, envName, caller) {
163 const filepath = (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
164 paths: [b]
165 }, M = require("module")) => {
166 let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
167
168 if (f) return f;
169 f = new Error(`Cannot resolve module '${r}'`);
170 f.code = "MODULE_NOT_FOUND";
171 throw f;
172 })(name, {
173 paths: [dirname]
174 });
175 const conf = yield* readConfig(filepath, envName, caller);
176
177 if (!conf) {
178 throw new Error(`Config file ${filepath} contains no configuration data`);
179 }
180
181 debug("Loaded config %o from %o.", name, dirname);
182 return conf;
183}
184
185function readConfig(filepath, envName, caller) {
186 const ext = _path().extname(filepath);
187
188 return ext === ".js" || ext === ".cjs" || ext === ".mjs" ? readConfigJS(filepath, {
189 envName,
190 caller
191 }) : readConfigJSON5(filepath);
192}
193
194const LOADING_CONFIGS = new Set();
195const readConfigJS = (0, _caching.makeStrongCache)(function* readConfigJS(filepath, cache) {
196 if (!_fs().existsSync(filepath)) {
197 cache.never();
198 return null;
199 }
200
201 if (LOADING_CONFIGS.has(filepath)) {
202 cache.never();
203 debug("Auto-ignoring usage of config %o.", filepath);
204 return {
205 filepath,
206 dirname: _path().dirname(filepath),
207 options: {}
208 };
209 }
210
211 let options;
212
213 try {
214 LOADING_CONFIGS.add(filepath);
215 options = yield* (0, _moduleTypes.default)(filepath, "You appear to be using a native ECMAScript module configuration " + "file, which is only supported when running Babel asynchronously.");
216 } catch (err) {
217 err.message = `${filepath}: Error while loading config - ${err.message}`;
218 throw err;
219 } finally {
220 LOADING_CONFIGS.delete(filepath);
221 }
222
223 let assertCache = false;
224
225 if (typeof options === "function") {
226 yield* [];
227 options = options((0, _configApi.makeConfigAPI)(cache));
228 assertCache = true;
229 }
230
231 if (!options || typeof options !== "object" || Array.isArray(options)) {
232 throw new Error(`${filepath}: Configuration should be an exported JavaScript object.`);
233 }
234
235 if (typeof options.then === "function") {
236 throw new Error(`You appear to be using an async configuration, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously return your config.`);
237 }
238
239 if (assertCache && !cache.configured()) throwConfigError();
240 return {
241 filepath,
242 dirname: _path().dirname(filepath),
243 options
244 };
245});
246const packageToBabelConfig = (0, _caching.makeWeakCacheSync)(file => {
247 const babel = file.options["babel"];
248 if (typeof babel === "undefined") return null;
249
250 if (typeof babel !== "object" || Array.isArray(babel) || babel === null) {
251 throw new Error(`${file.filepath}: .babel property must be an object`);
252 }
253
254 return {
255 filepath: file.filepath,
256 dirname: file.dirname,
257 options: babel
258 };
259});
260const readConfigJSON5 = (0, _utils.makeStaticFileCache)((filepath, content) => {
261 let options;
262
263 try {
264 options = _json().parse(content);
265 } catch (err) {
266 err.message = `${filepath}: Error while parsing config - ${err.message}`;
267 throw err;
268 }
269
270 if (!options) throw new Error(`${filepath}: No config detected`);
271
272 if (typeof options !== "object") {
273 throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
274 }
275
276 if (Array.isArray(options)) {
277 throw new Error(`${filepath}: Expected config object but found array`);
278 }
279
280 delete options["$schema"];
281 return {
282 filepath,
283 dirname: _path().dirname(filepath),
284 options
285 };
286});
287const readIgnoreConfig = (0, _utils.makeStaticFileCache)((filepath, content) => {
288 const ignoreDir = _path().dirname(filepath);
289
290 const ignorePatterns = content.split("\n").map(line => line.replace(/#(.*?)$/, "").trim()).filter(line => !!line);
291
292 for (const pattern of ignorePatterns) {
293 if (pattern[0] === "!") {
294 throw new Error(`Negation of file paths is not supported.`);
295 }
296 }
297
298 return {
299 filepath,
300 dirname: _path().dirname(filepath),
301 ignore: ignorePatterns.map(pattern => (0, _patternToRegex.default)(pattern, ignoreDir))
302 };
303});
304
305function* resolveShowConfigPath(dirname) {
306 const targetPath = process.env.BABEL_SHOW_CONFIG_FOR;
307
308 if (targetPath != null) {
309 const absolutePath = _path().resolve(dirname, targetPath);
310
311 const stats = yield* fs.stat(absolutePath);
312
313 if (!stats.isFile()) {
314 throw new Error(`${absolutePath}: BABEL_SHOW_CONFIG_FOR must refer to a regular file, directories are not supported.`);
315 }
316
317 return absolutePath;
318 }
319
320 return null;
321}
322
323function throwConfigError() {
324 throw new Error(`\
325Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured
326for various types of caching, using the first param of their handler functions:
327
328module.exports = function(api) {
329 // The API exposes the following:
330
331 // Cache the returned value forever and don't call this function again.
332 api.cache(true);
333
334 // Don't cache at all. Not recommended because it will be very slow.
335 api.cache(false);
336
337 // Cached based on the value of some function. If this function returns a value different from
338 // a previously-encountered value, the plugins will re-evaluate.
339 var env = api.cache(() => process.env.NODE_ENV);
340
341 // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for
342 // any possible NODE_ENV value that might come up during plugin execution.
343 var isProd = api.cache(() => process.env.NODE_ENV === "production");
344
345 // .cache(fn) will perform a linear search though instances to find the matching plugin based
346 // based on previous instantiated plugins. If you want to recreate the plugin and discard the
347 // previous instance whenever something changes, you may use:
348 var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");
349
350 // Note, we also expose the following more-verbose versions of the above examples:
351 api.cache.forever(); // api.cache(true)
352 api.cache.never(); // api.cache(false)
353 api.cache.using(fn); // api.cache(fn)
354
355 // Return the value that will be cached.
356 return { };
357};`);
358}
\No newline at end of file