Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support monorepos by allowing users to opt into autoconfiguring "root" #8636

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 12 additions & 6 deletions packages/babel-core/src/config/config-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export type PresetInstance = {
export type ConfigContext = {
filename: string | void,
cwd: string,
root: string,
root: string | false,
envName: string,
caller: CallerMetadata | void,
};
Expand Down Expand Up @@ -150,7 +150,7 @@ export function buildRootChain(
context.envName,
context.caller,
);
} else if (opts.configFile !== false) {
} else if (opts.configFile !== false && context.root !== false) {
configFile = findRootConfig(context.root, context.envName, context.caller);
}

Expand Down Expand Up @@ -237,6 +237,8 @@ function babelrcLoadEnabled(
// Fast path to avoid having to match patterns if the babelrc is just
// loading in the standard root directory.
if (babelrcRoots === undefined) {
if (absoluteRoot === false) return false;

return pkgData.directories.indexOf(absoluteRoot) !== -1;
}

Expand All @@ -248,7 +250,11 @@ function babelrcLoadEnabled(

// Fast path to avoid having to match patterns if the babelrc is just
// loading in the standard root directory.
if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {
if (
absoluteRoot !== false &&
babelrcPatterns.length === 1 &&
babelrcPatterns[0] === absoluteRoot
) {
return pkgData.directories.indexOf(absoluteRoot) !== -1;
}

Expand Down Expand Up @@ -661,9 +667,9 @@ function matchesPatterns(
}

function matchPattern(
pattern,
dirname,
pathToTest,
pattern: string | RegExp | Function,
dirname: string,
pathToTest: string | void,
context: ConfigContext,
): boolean {
if (typeof pattern === "function") {
Expand Down
18 changes: 18 additions & 0 deletions packages/babel-core/src/config/files/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js";
const BABELIGNORE_FILENAME = ".babelignore";

export function findConfigRoot(cwd: string): string {
let dirname = cwd;
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;
}

throw new Error(
`Babel was run with root:true but a root babel.config.js could not ` +
`be found when searching from "${dirname}"`,
);
}

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

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

export function findConfigRoot(
cwd: string, // eslint-disable-line no-unused-vars
): string {
throw new Error(
`Cannot search for filesystem config root when running in a browser`,
);
}

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

export {
findConfigRoot,
findRelativeConfig,
findRootConfig,
loadConfig,
Expand Down
9 changes: 7 additions & 2 deletions packages/babel-core/src/config/partial.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { buildRootChain, type ConfigContext } from "./config-chain";
import { getEnv } from "./helpers/environment";
import { validate, type ValidatedOptions } from "./validation/options";

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

export default function loadPrivatePartialConfig(
inputOpts: mixed,
Expand All @@ -30,7 +30,12 @@ export default function loadPrivatePartialConfig(

const { envName = getEnv(), cwd = ".", root: rootDir = ".", caller } = args;
const absoluteCwd = path.resolve(cwd);
const absoluteRootDir = path.resolve(absoluteCwd, rootDir);
const absoluteRootDir =
typeof rootDir === "boolean"
? rootDir
? findConfigRoot(absoluteCwd)
: false
: path.resolve(absoluteCwd, rootDir);

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

export type ValidatorSet = {
Expand Down Expand Up @@ -77,6 +78,17 @@ export function assertSourceMaps(
return value;
}

export function assertRoot(loc: OptionPath, value: mixed): ProjectRoot | void {
if (
value !== undefined &&
typeof value !== "boolean" &&
typeof value !== "string"
) {
throw new Error(`${msg(loc)} must be a string, false, or undefined`);
}
return value;
}

export function assertCompact(
loc: OptionPath,
value: mixed,
Expand Down
6 changes: 4 additions & 2 deletions packages/babel-core/src/config/validation/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ import {
assertSourceMaps,
assertCompact,
assertSourceType,
assertRoot,
type ValidatorSet,
type Validator,
type OptionPath,
} from "./option-assertions";

const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
root: (assertRoot: Validator<$PropertyType<ValidatedOptions, "root">>),
configFile: (assertConfigFileSearch: Validator<
$PropertyType<ValidatedOptions, "configFile">,
>),
Expand Down Expand Up @@ -175,7 +176,7 @@ export type ValidatedOptions = {
babelrc?: boolean,
babelrcRoots?: BabelrcSearch,
configFile?: ConfigFileSearch,
root?: string,
root?: ProjectRoot,
code?: boolean,
ast?: boolean,
inputSourceMap?: RootInputSourceMapOption,
Expand Down Expand Up @@ -260,6 +261,7 @@ export type SourceMapsOption = boolean | "inline" | "both";
export type SourceTypeOption = "module" | "script" | "unambiguous";
export type CompactOption = boolean | "auto";
export type RootInputSourceMapOption = {} | boolean;
export type ProjectRoot = string | boolean;

export type OptionsSource =
| "arguments"
Expand Down