Skip to content

Commit

Permalink
Allow users to choose how the configuration root is selected. (#8660)
Browse files Browse the repository at this point in the history
  • Loading branch information
loganfsmyth committed Sep 15, 2018
1 parent aac8118 commit bd0c62d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 4 deletions.
6 changes: 6 additions & 0 deletions packages/babel-cli/src/babel/options.js
Expand Up @@ -28,6 +28,11 @@ commander.option(
"The name of the 'env' to use when loading configs and plugins. " +
"Defaults to the value of BABEL_ENV, or else NODE_ENV, or else 'development'.",
);
commander.option(
"--root-mode [mode]",
"The project-root resolution mode. " +
"One of 'root' (the default), 'upward', or 'upward-optional'.",
);

// Basic file input configuration.
commander.option("--source-type [script|module]", "");
Expand Down Expand Up @@ -220,6 +225,7 @@ export default function parseArgv(args: Array<string>) {
babelOptions: {
presets: opts.presets,
plugins: opts.plugins,
rootMode: opts.rootMode,
configFile: opts.configFile,
envName: opts.envName,
sourceType: opts.sourceType,
Expand Down
15 changes: 15 additions & 0 deletions packages/babel-core/src/config/files/configuration.js
Expand Up @@ -24,6 +24,21 @@ const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js";
const BABELIGNORE_FILENAME = ".babelignore";

export function findConfigUpwards(rootDir: string): string | null {
let dirname = rootDir;
while (true) {
if (fs.existsSync(path.join(dirname, BABEL_CONFIG_JS_FILENAME))) {
return dirname;
}

const nextDir = path.dirname(dirname);
if (dirname === nextDir) break;
dirname = nextDir;
}

return null;
}

export function findRelativeConfig(
packageData: FilePackageData,
envName: string,
Expand Down
6 changes: 6 additions & 0 deletions packages/babel-core/src/config/files/index-browser.js
Expand Up @@ -11,6 +11,12 @@ import type { CallerMetadata } from "../validation/options";

export type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };

export function findConfigUpwards(
rootDir: string, // eslint-disable-line no-unused-vars
): string | null {
return null;
}

export function findPackageData(filepath: string): FilePackageData {
return {
filepath,
Expand Down
1 change: 1 addition & 0 deletions packages/babel-core/src/config/files/index.js
Expand Up @@ -10,6 +10,7 @@ import typeof * as indexType from "./index";
export { findPackageData } from "./package";

export {
findConfigUpwards,
findRelativeConfig,
findRootConfig,
loadConfig,
Expand Down
51 changes: 47 additions & 4 deletions packages/babel-core/src/config/partial.js
Expand Up @@ -6,9 +6,43 @@ import { mergeOptions } from "./util";
import { createItemFromDescriptor } from "./item";
import { buildRootChain, type ConfigContext } from "./config-chain";
import { getEnv } from "./helpers/environment";
import { validate, type ValidatedOptions } from "./validation/options";
import {
validate,
type ValidatedOptions,
type RootMode,
} from "./validation/options";

import { findConfigUpwards, type ConfigFile, type IgnoreFile } from "./files";

function resolveRootMode(rootDir: string, rootMode: RootMode): string {
switch (rootMode) {
case "root":
return rootDir;

case "upward-optional": {
const upwardRootDir = findConfigUpwards(rootDir);
return upwardRootDir === null ? rootDir : upwardRootDir;
}

import type { ConfigFile, IgnoreFile } from "./files";
case "upward": {
const upwardRootDir = findConfigUpwards(rootDir);
if (upwardRootDir !== null) return upwardRootDir;

throw Object.assign(
(new Error(
`Babel was run with rootMode:"upward" but a root could not ` +
`be found when searching upward from "${rootDir}"`,
): any),
{
code: "BABEL_ROOT_NOT_FOUND",
dirname: rootDir,
},
);
}
default:
throw new Error(`Assertion failure - unknown rootMode value`);
}
}

export default function loadPrivatePartialConfig(
inputOpts: mixed,
Expand All @@ -28,9 +62,18 @@ export default function loadPrivatePartialConfig(

const args = inputOpts ? validate("arguments", inputOpts) : {};

const { envName = getEnv(), cwd = ".", root: rootDir = ".", caller } = args;
const {
envName = getEnv(),
cwd = ".",
root: rootDir = ".",
rootMode = "root",
caller,
} = args;
const absoluteCwd = path.resolve(cwd);
const absoluteRootDir = path.resolve(absoluteCwd, rootDir);
const absoluteRootDir = resolveRootMode(
path.resolve(absoluteCwd, rootDir),
rootMode,
);

const context: ConfigContext = {
filename:
Expand Down
15 changes: 15 additions & 0 deletions packages/babel-core/src/config/validation/option-assertions.js
Expand Up @@ -15,6 +15,7 @@ import type {
RootInputSourceMapOption,
NestingPath,
CallerMetadata,
RootMode,
} from "./options";

export type ValidatorSet = {
Expand Down Expand Up @@ -60,6 +61,20 @@ type AccessPath = $ReadOnly<{
}>;
type GeneralPath = OptionPath | AccessPath;

export function assertRootMode(loc: OptionPath, value: mixed): RootMode | void {
if (
value !== undefined &&
value !== "root" &&
value !== "upward" &&
value !== "upward-optional"
) {
throw new Error(
`${msg(loc)} must be a "root", "upward", "upward-optional" or undefined`,
);
}
return value;
}

export function assertSourceMaps(
loc: OptionPath,
value: mixed,
Expand Down
6 changes: 6 additions & 0 deletions packages/babel-core/src/config/validation/options.js
Expand Up @@ -19,6 +19,7 @@ import {
assertConfigFileSearch,
assertBabelrcSearch,
assertFunction,
assertRootMode,
assertSourceMaps,
assertCompact,
assertSourceType,
Expand All @@ -30,6 +31,9 @@ import {
const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
rootMode: (assertRootMode: Validator<
$PropertyType<ValidatedOptions, "rootMode">,
>),
configFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "configFile">,
>),
Expand Down Expand Up @@ -176,6 +180,7 @@ export type ValidatedOptions = {
babelrcRoots?: BabelrcSearch,
configFile?: ConfigFileSearch,
root?: string,
rootMode?: RootMode,
code?: boolean,
ast?: boolean,
inputSourceMap?: RootInputSourceMapOption,
Expand Down Expand Up @@ -260,6 +265,7 @@ export type SourceMapsOption = boolean | "inline" | "both";
export type SourceTypeOption = "module" | "script" | "unambiguous";
export type CompactOption = boolean | "auto";
export type RootInputSourceMapOption = {} | boolean;
export type RootMode = "root" | "upward" | "upward-optional";

export type OptionsSource =
| "arguments"
Expand Down

0 comments on commit bd0c62d

Please sign in to comment.