Support a babel.config.fs file in a 'root' directory.

This commit is contained in:
Logan Smyth 2018-03-08 13:21:31 -08:00
parent f013dab5fb
commit 485e37fcb0
8 changed files with 86 additions and 8 deletions

View File

@ -238,10 +238,6 @@ if (errors.length) {
//
const opts = commander.opts();
//the configFile CLI option maps to the extends option in the node API
if (opts.configFile) {
opts.extends = opts.configFile;
}
// Delete options that are specific to @babel/cli and shouldn't be passed to @babel/core.
delete opts.version;
@ -253,7 +249,6 @@ delete opts.outDir;
delete opts.copyFiles;
delete opts.includeDotfiles;
delete opts.verbose;
delete opts.configFile;
delete opts.deleteDirOnStart;
delete opts.keepFileExtension;
delete opts.relative;

View File

@ -15,6 +15,7 @@ const debug = buildDebug("babel:config:config-chain");
import {
findPackageData,
findRelativeConfig,
findRootConfig,
loadConfig,
type ConfigFile,
type IgnoreFile,
@ -107,6 +108,7 @@ const loadPresetOverridesEnvDescriptors = makeWeakCache(
export type RootConfigChain = ConfigChain & {
babelrc: ConfigFile | void,
config: ConfigFile | void,
ignore: IgnoreFile | void,
};
@ -126,6 +128,26 @@ export function buildRootChain(
);
if (!programmaticChain) return null;
const { root: rootDir = ".", configFile: configFileName } = opts;
let configFile;
if (typeof configFileName === "string") {
configFile = loadConfig(configFileName, context.cwd, context.envName);
} else if (configFileName === undefined || configFileName === true) {
configFile = findRootConfig(
path.resolve(context.cwd, rootDir),
context.envName,
);
}
const configFileChain = emptyChain();
if (configFile) {
const result = loadFileChain(configFile, context);
if (!result) return null;
mergeChain(configFileChain, result);
}
const pkgData =
typeof context.filename === "string"
? findPackageData(context.filename)
@ -155,7 +177,7 @@ export function buildRootChain(
// Insert file chain in front so programmatic options have priority
// over configuration file chain items.
const chain = mergeChain(
mergeChain(emptyChain(), fileChain),
mergeChain(mergeChain(emptyChain(), configFileChain), fileChain),
programmaticChain,
);
@ -165,6 +187,7 @@ export function buildRootChain(
options: chain.options.map(o => normalizeOptions(o)),
ignore: ignore || undefined,
babelrc: babelrc || undefined,
config: configFile || undefined,
};
}

View File

@ -16,6 +16,8 @@ import type { FilePackageData, RelativeConfig, ConfigFile } from "./types";
const debug = buildDebug("babel:config:loading:files:configuration");
const BABEL_CONFIG_JS_FILENAME = "babel.config.js";
const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js";
const BABELIGNORE_FILENAME = ".babelignore";
@ -85,6 +87,19 @@ export function findRelativeConfig(
return { config, ignore };
}
export function findRootConfig(
dirname: string,
envName: string,
): ConfigFile | null {
const filepath = path.resolve(dirname, BABEL_CONFIG_JS_FILENAME);
const conf = readConfig(filepath, envName);
if (conf) {
debug("Found root config %o in $o.", BABEL_CONFIG_JS_FILENAME, dirname);
}
return conf;
}
export function loadConfig(
name: string,
dirname: string,

View File

@ -25,6 +25,13 @@ export function findRelativeConfig(
return { pkg: null, config: null, ignore: null };
}
export function findRootConfig(
dirname: string,
envName: string, // eslint-disable-line no-unused-vars
): ConfigFile | null {
return null;
}
export function loadConfig(
name: string,
dirname: string,

View File

@ -9,7 +9,11 @@ import typeof * as indexType from "./index";
export { findPackageData } from "./package";
export { findRelativeConfig, loadConfig } from "./configuration";
export {
findRelativeConfig,
findRootConfig,
loadConfig,
} from "./configuration";
export type {
ConfigFile,
IgnoreFile,

View File

@ -17,6 +17,7 @@ export default function loadPrivatePartialConfig(
context: ConfigContext,
ignore: IgnoreFile | void,
babelrc: ConfigFile | void,
config: ConfigFile | void,
} | null {
if (
inputOpts != null &&
@ -64,6 +65,7 @@ export default function loadPrivatePartialConfig(
context,
ignore: configChain.ignore,
babelrc: configChain.babelrc,
config: configChain.config,
};
}
@ -71,7 +73,7 @@ export function loadPartialConfig(inputOpts: mixed): PartialConfig | null {
const result = loadPrivatePartialConfig(inputOpts);
if (!result) return null;
const { options, babelrc, ignore } = result;
const { options, babelrc, ignore, config } = result;
(options.plugins || []).forEach(item => {
if (item.value instanceof Plugin) {
@ -86,6 +88,7 @@ export function loadPartialConfig(inputOpts: mixed): PartialConfig | null {
options,
babelrc ? babelrc.filepath : undefined,
ignore ? ignore.filepath : undefined,
config ? config.filepath : undefined,
);
}
@ -99,15 +102,18 @@ class PartialConfig {
options: ValidatedOptions;
babelrc: string | void;
babelignore: string | void;
config: string | void;
constructor(
options: ValidatedOptions,
babelrc: string | void,
ignore: string | void,
config: string | void,
) {
this.options = options;
this.babelignore = ignore;
this.babelrc = babelrc;
this.config = config;
// Freeze since this is a public API and it should be extremely obvious that
// reassigning properties on here does nothing.

View File

@ -1,6 +1,7 @@
// @flow
import type {
ConfigFileSearch,
IgnoreList,
IgnoreItem,
PluginList,
@ -164,6 +165,24 @@ function checkValidTest(value: mixed): boolean {
);
}
export function assertConfigFileSearch(
key: string,
value: mixed,
): ConfigFileSearch | void {
if (
value !== undefined &&
typeof value !== "boolean" &&
typeof value !== "string"
) {
throw new Error(
`.${key} must be a undefined, a boolean, a string, ` +
`got ${JSON.stringify(value)}`,
);
}
return value;
}
export function assertPluginList(key: string, value: mixed): PluginList | void {
const arr = assertArray(key, value);
if (arr) {

View File

@ -13,6 +13,7 @@ import {
assertIgnoreList,
assertPluginList,
assertConfigApplicableTest,
assertConfigFileSearch,
assertFunction,
assertSourceMaps,
assertCompact,
@ -23,6 +24,11 @@ import {
const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
configFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "configFile">,
>),
filename: (assertString: Validator<
$PropertyType<ValidatedOptions, "filename">,
>),
@ -152,6 +158,8 @@ export type ValidatedOptions = {
filenameRelative?: string,
babelrc?: boolean,
code?: boolean,
configFile?: ConfigFileSearch,
root?: string,
ast?: boolean,
inputSourceMap?: RootInputSourceMapOption,
envName?: string,
@ -223,6 +231,7 @@ export type PluginList = $ReadOnlyArray<PluginItem>;
export type OverridesList = Array<ValidatedOptions>;
export type ConfigApplicableTest = IgnoreItem | Array<IgnoreItem>;
export type ConfigFileSearch = string | boolean;
export type SourceMapsOption = boolean | "inline" | "both";
export type SourceTypeOption = "module" | "script" | "unambiguous";
export type CompactOption = boolean | "auto";