| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.buildPresetChain = buildPresetChain; |
| exports.buildRootChain = buildRootChain; |
| exports.buildPresetChainWalker = void 0; |
| |
| function _path() { |
| const data = _interopRequireDefault(require("path")); |
| |
| _path = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| function _debug() { |
| const data = _interopRequireDefault(require("debug")); |
| |
| _debug = function () { |
| return data; |
| }; |
| |
| return data; |
| } |
| |
| var _options = require("./validation/options"); |
| |
| var _patternToRegex = _interopRequireDefault(require("./pattern-to-regex")); |
| |
| var _files = require("./files"); |
| |
| var _caching = require("./caching"); |
| |
| var _configDescriptors = require("./config-descriptors"); |
| |
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
| |
| const debug = (0, _debug().default)("babel:config:config-chain"); |
| |
| function buildPresetChain(arg, context) { |
| const chain = buildPresetChainWalker(arg, context); |
| if (!chain) return null; |
| return { |
| plugins: dedupDescriptors(chain.plugins), |
| presets: dedupDescriptors(chain.presets), |
| options: chain.options.map(o => normalizeOptions(o)) |
| }; |
| } |
| |
| const buildPresetChainWalker = makeChainWalker({ |
| init: arg => arg, |
| root: preset => loadPresetDescriptors(preset), |
| env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName), |
| overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index), |
| overridesEnv: (preset, index, envName) => loadPresetOverridesEnvDescriptors(preset)(index)(envName) |
| }); |
| exports.buildPresetChainWalker = buildPresetChainWalker; |
| const loadPresetDescriptors = (0, _caching.makeWeakCache)(preset => buildRootDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors)); |
| const loadPresetEnvDescriptors = (0, _caching.makeWeakCache)(preset => (0, _caching.makeStrongCache)(envName => buildEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, envName))); |
| const loadPresetOverridesDescriptors = (0, _caching.makeWeakCache)(preset => (0, _caching.makeStrongCache)(index => buildOverrideDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index))); |
| const loadPresetOverridesEnvDescriptors = (0, _caching.makeWeakCache)(preset => (0, _caching.makeStrongCache)(index => (0, _caching.makeStrongCache)(envName => buildOverrideEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index, envName)))); |
| |
| function buildRootChain(opts, context) { |
| const programmaticChain = loadProgrammaticChain({ |
| options: opts, |
| dirname: context.cwd |
| }, context); |
| if (!programmaticChain) return null; |
| let configFile; |
| |
| if (typeof opts.configFile === "string") { |
| configFile = (0, _files.loadConfig)(opts.configFile, context.cwd, context.envName, context.caller); |
| } else if (opts.configFile !== false) { |
| configFile = (0, _files.findRootConfig)(context.root, context.envName, context.caller); |
| } |
| |
| let { |
| babelrc, |
| babelrcRoots |
| } = opts; |
| let babelrcRootsDirectory = context.cwd; |
| const configFileChain = emptyChain(); |
| |
| if (configFile) { |
| const validatedFile = validateConfigFile(configFile); |
| const result = loadFileChain(validatedFile, context); |
| if (!result) return null; |
| |
| if (babelrc === undefined) { |
| babelrc = validatedFile.options.babelrc; |
| } |
| |
| if (babelrcRoots === undefined) { |
| babelrcRootsDirectory = validatedFile.dirname; |
| babelrcRoots = validatedFile.options.babelrcRoots; |
| } |
| |
| mergeChain(configFileChain, result); |
| } |
| |
| const pkgData = typeof context.filename === "string" ? (0, _files.findPackageData)(context.filename) : null; |
| let ignoreFile, babelrcFile; |
| const fileChain = emptyChain(); |
| |
| if ((babelrc === true || babelrc === undefined) && pkgData && babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)) { |
| ({ |
| ignore: ignoreFile, |
| config: babelrcFile |
| } = (0, _files.findRelativeConfig)(pkgData, context.envName, context.caller)); |
| |
| if (ignoreFile && shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)) { |
| return null; |
| } |
| |
| if (babelrcFile) { |
| const result = loadFileChain(validateBabelrcFile(babelrcFile), context); |
| if (!result) return null; |
| mergeChain(fileChain, result); |
| } |
| } |
| |
| const chain = mergeChain(mergeChain(mergeChain(emptyChain(), configFileChain), fileChain), programmaticChain); |
| return { |
| plugins: dedupDescriptors(chain.plugins), |
| presets: dedupDescriptors(chain.presets), |
| options: chain.options.map(o => normalizeOptions(o)), |
| ignore: ignoreFile || undefined, |
| babelrc: babelrcFile || undefined, |
| config: configFile || undefined |
| }; |
| } |
| |
| function babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory) { |
| if (typeof babelrcRoots === "boolean") return babelrcRoots; |
| const absoluteRoot = context.root; |
| |
| if (babelrcRoots === undefined) { |
| return pkgData.directories.indexOf(absoluteRoot) !== -1; |
| } |
| |
| let babelrcPatterns = babelrcRoots; |
| if (!Array.isArray(babelrcPatterns)) babelrcPatterns = [babelrcPatterns]; |
| babelrcPatterns = babelrcPatterns.map(pat => { |
| return typeof pat === "string" ? _path().default.resolve(babelrcRootsDirectory, pat) : pat; |
| }); |
| |
| if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) { |
| return pkgData.directories.indexOf(absoluteRoot) !== -1; |
| } |
| |
| return babelrcPatterns.some(pat => { |
| if (typeof pat === "string") { |
| pat = (0, _patternToRegex.default)(pat, babelrcRootsDirectory); |
| } |
| |
| return pkgData.directories.some(directory => { |
| return matchPattern(pat, babelrcRootsDirectory, directory, context); |
| }); |
| }); |
| } |
| |
| const validateConfigFile = (0, _caching.makeWeakCache)(file => ({ |
| filepath: file.filepath, |
| dirname: file.dirname, |
| options: (0, _options.validate)("configfile", file.options) |
| })); |
| const validateBabelrcFile = (0, _caching.makeWeakCache)(file => ({ |
| filepath: file.filepath, |
| dirname: file.dirname, |
| options: (0, _options.validate)("babelrcfile", file.options) |
| })); |
| const validateExtendFile = (0, _caching.makeWeakCache)(file => ({ |
| filepath: file.filepath, |
| dirname: file.dirname, |
| options: (0, _options.validate)("extendsfile", file.options) |
| })); |
| const loadProgrammaticChain = makeChainWalker({ |
| root: input => buildRootDescriptors(input, "base", _configDescriptors.createCachedDescriptors), |
| env: (input, envName) => buildEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, envName), |
| overrides: (input, index) => buildOverrideDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index), |
| overridesEnv: (input, index, envName) => buildOverrideEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index, envName) |
| }); |
| const loadFileChain = makeChainWalker({ |
| root: file => loadFileDescriptors(file), |
| env: (file, envName) => loadFileEnvDescriptors(file)(envName), |
| overrides: (file, index) => loadFileOverridesDescriptors(file)(index), |
| overridesEnv: (file, index, envName) => loadFileOverridesEnvDescriptors(file)(index)(envName) |
| }); |
| const loadFileDescriptors = (0, _caching.makeWeakCache)(file => buildRootDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors)); |
| const loadFileEnvDescriptors = (0, _caching.makeWeakCache)(file => (0, _caching.makeStrongCache)(envName => buildEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, envName))); |
| const loadFileOverridesDescriptors = (0, _caching.makeWeakCache)(file => (0, _caching.makeStrongCache)(index => buildOverrideDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index))); |
| const loadFileOverridesEnvDescriptors = (0, _caching.makeWeakCache)(file => (0, _caching.makeStrongCache)(index => (0, _caching.makeStrongCache)(envName => buildOverrideEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index, envName)))); |
| |
| function buildRootDescriptors({ |
| dirname, |
| options |
| }, alias, descriptors) { |
| return descriptors(dirname, options, alias); |
| } |
| |
| function buildEnvDescriptors({ |
| dirname, |
| options |
| }, alias, descriptors, envName) { |
| const opts = options.env && options.env[envName]; |
| return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null; |
| } |
| |
| function buildOverrideDescriptors({ |
| dirname, |
| options |
| }, alias, descriptors, index) { |
| const opts = options.overrides && options.overrides[index]; |
| if (!opts) throw new Error("Assertion failure - missing override"); |
| return descriptors(dirname, opts, `${alias}.overrides[${index}]`); |
| } |
| |
| function buildOverrideEnvDescriptors({ |
| dirname, |
| options |
| }, alias, descriptors, index, envName) { |
| const override = options.overrides && options.overrides[index]; |
| if (!override) throw new Error("Assertion failure - missing override"); |
| const opts = override.env && override.env[envName]; |
| return opts ? descriptors(dirname, opts, `${alias}.overrides[${index}].env["${envName}"]`) : null; |
| } |
| |
| function makeChainWalker({ |
| root, |
| env, |
| overrides, |
| overridesEnv |
| }) { |
| return (input, context, files = new Set()) => { |
| const { |
| dirname |
| } = input; |
| const flattenedConfigs = []; |
| const rootOpts = root(input); |
| |
| if (configIsApplicable(rootOpts, dirname, context)) { |
| flattenedConfigs.push(rootOpts); |
| const envOpts = env(input, context.envName); |
| |
| if (envOpts && configIsApplicable(envOpts, dirname, context)) { |
| flattenedConfigs.push(envOpts); |
| } |
| |
| (rootOpts.options.overrides || []).forEach((_, index) => { |
| const overrideOps = overrides(input, index); |
| |
| if (configIsApplicable(overrideOps, dirname, context)) { |
| flattenedConfigs.push(overrideOps); |
| const overrideEnvOpts = overridesEnv(input, index, context.envName); |
| |
| if (overrideEnvOpts && configIsApplicable(overrideEnvOpts, dirname, context)) { |
| flattenedConfigs.push(overrideEnvOpts); |
| } |
| } |
| }); |
| } |
| |
| if (flattenedConfigs.some(({ |
| options: { |
| ignore, |
| only |
| } |
| }) => shouldIgnore(context, ignore, only, dirname))) { |
| return null; |
| } |
| |
| const chain = emptyChain(); |
| |
| for (const op of flattenedConfigs) { |
| if (!mergeExtendsChain(chain, op.options, dirname, context, files)) { |
| return null; |
| } |
| |
| mergeChainOpts(chain, op); |
| } |
| |
| return chain; |
| }; |
| } |
| |
| function mergeExtendsChain(chain, opts, dirname, context, files) { |
| if (opts.extends === undefined) return true; |
| const file = (0, _files.loadConfig)(opts.extends, dirname, context.envName, context.caller); |
| |
| if (files.has(file)) { |
| throw new Error(`Configuration cycle detected loading ${file.filepath}.\n` + `File already loaded following the config chain:\n` + Array.from(files, file => ` - ${file.filepath}`).join("\n")); |
| } |
| |
| files.add(file); |
| const fileChain = loadFileChain(validateExtendFile(file), context, files); |
| files.delete(file); |
| if (!fileChain) return false; |
| mergeChain(chain, fileChain); |
| return true; |
| } |
| |
| function mergeChain(target, source) { |
| target.options.push(...source.options); |
| target.plugins.push(...source.plugins); |
| target.presets.push(...source.presets); |
| return target; |
| } |
| |
| function mergeChainOpts(target, { |
| options, |
| plugins, |
| presets |
| }) { |
| target.options.push(options); |
| target.plugins.push(...plugins()); |
| target.presets.push(...presets()); |
| return target; |
| } |
| |
| function emptyChain() { |
| return { |
| options: [], |
| presets: [], |
| plugins: [] |
| }; |
| } |
| |
| function normalizeOptions(opts) { |
| const options = Object.assign({}, opts); |
| delete options.extends; |
| delete options.env; |
| delete options.overrides; |
| delete options.plugins; |
| delete options.presets; |
| delete options.passPerPreset; |
| delete options.ignore; |
| delete options.only; |
| delete options.test; |
| delete options.include; |
| delete options.exclude; |
| |
| if (options.hasOwnProperty("sourceMap")) { |
| options.sourceMaps = options.sourceMap; |
| delete options.sourceMap; |
| } |
| |
| return options; |
| } |
| |
| function dedupDescriptors(items) { |
| const map = new Map(); |
| const descriptors = []; |
| |
| for (const item of items) { |
| if (typeof item.value === "function") { |
| const fnKey = item.value; |
| let nameMap = map.get(fnKey); |
| |
| if (!nameMap) { |
| nameMap = new Map(); |
| map.set(fnKey, nameMap); |
| } |
| |
| let desc = nameMap.get(item.name); |
| |
| if (!desc) { |
| desc = { |
| value: item |
| }; |
| descriptors.push(desc); |
| if (!item.ownPass) nameMap.set(item.name, desc); |
| } else { |
| desc.value = item; |
| } |
| } else { |
| descriptors.push({ |
| value: item |
| }); |
| } |
| } |
| |
| return descriptors.reduce((acc, desc) => { |
| acc.push(desc.value); |
| return acc; |
| }, []); |
| } |
| |
| function configIsApplicable({ |
| options |
| }, dirname, context) { |
| return (options.test === undefined || configFieldIsApplicable(context, options.test, dirname)) && (options.include === undefined || configFieldIsApplicable(context, options.include, dirname)) && (options.exclude === undefined || !configFieldIsApplicable(context, options.exclude, dirname)); |
| } |
| |
| function configFieldIsApplicable(context, test, dirname) { |
| const patterns = Array.isArray(test) ? test : [test]; |
| return matchesPatterns(context, patterns, dirname); |
| } |
| |
| function shouldIgnore(context, ignore, only, dirname) { |
| if (ignore && matchesPatterns(context, ignore, dirname)) { |
| debug("Ignored %o because it matched one of %O from %o", context.filename, ignore, dirname); |
| return true; |
| } |
| |
| if (only && !matchesPatterns(context, only, dirname)) { |
| debug("Ignored %o because it failed to match one of %O from %o", context.filename, only, dirname); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| function matchesPatterns(context, patterns, dirname) { |
| return patterns.some(pattern => matchPattern(pattern, dirname, context.filename, context)); |
| } |
| |
| function matchPattern(pattern, dirname, pathToTest, context) { |
| if (typeof pattern === "function") { |
| return !!pattern(pathToTest, { |
| dirname, |
| envName: context.envName, |
| caller: context.caller |
| }); |
| } |
| |
| if (typeof pathToTest !== "string") { |
| throw new Error(`Configuration contains string/RegExp pattern, but no filename was passed to Babel`); |
| } |
| |
| if (typeof pattern === "string") { |
| pattern = (0, _patternToRegex.default)(pattern, dirname); |
| } |
| |
| return pattern.test(pathToTest); |
| } |