Allow users to choose how the configuration root is selected. (#8660)
This commit is contained in:
parent
aac8118b7f
commit
bd0c62dc0c
@ -28,6 +28,11 @@ commander.option(
|
|||||||
"The name of the 'env' to use when loading configs and plugins. " +
|
"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'.",
|
"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.
|
// Basic file input configuration.
|
||||||
commander.option("--source-type [script|module]", "");
|
commander.option("--source-type [script|module]", "");
|
||||||
@ -220,6 +225,7 @@ export default function parseArgv(args: Array<string>) {
|
|||||||
babelOptions: {
|
babelOptions: {
|
||||||
presets: opts.presets,
|
presets: opts.presets,
|
||||||
plugins: opts.plugins,
|
plugins: opts.plugins,
|
||||||
|
rootMode: opts.rootMode,
|
||||||
configFile: opts.configFile,
|
configFile: opts.configFile,
|
||||||
envName: opts.envName,
|
envName: opts.envName,
|
||||||
sourceType: opts.sourceType,
|
sourceType: opts.sourceType,
|
||||||
|
|||||||
@ -24,6 +24,21 @@ const BABELRC_FILENAME = ".babelrc";
|
|||||||
const BABELRC_JS_FILENAME = ".babelrc.js";
|
const BABELRC_JS_FILENAME = ".babelrc.js";
|
||||||
const BABELIGNORE_FILENAME = ".babelignore";
|
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(
|
export function findRelativeConfig(
|
||||||
packageData: FilePackageData,
|
packageData: FilePackageData,
|
||||||
envName: string,
|
envName: string,
|
||||||
|
|||||||
@ -11,6 +11,12 @@ import type { CallerMetadata } from "../validation/options";
|
|||||||
|
|
||||||
export type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };
|
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 {
|
export function findPackageData(filepath: string): FilePackageData {
|
||||||
return {
|
return {
|
||||||
filepath,
|
filepath,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import typeof * as indexType from "./index";
|
|||||||
export { findPackageData } from "./package";
|
export { findPackageData } from "./package";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
findConfigUpwards,
|
||||||
findRelativeConfig,
|
findRelativeConfig,
|
||||||
findRootConfig,
|
findRootConfig,
|
||||||
loadConfig,
|
loadConfig,
|
||||||
|
|||||||
@ -6,9 +6,43 @@ import { mergeOptions } from "./util";
|
|||||||
import { createItemFromDescriptor } from "./item";
|
import { createItemFromDescriptor } from "./item";
|
||||||
import { buildRootChain, type ConfigContext } from "./config-chain";
|
import { buildRootChain, type ConfigContext } from "./config-chain";
|
||||||
import { getEnv } from "./helpers/environment";
|
import { getEnv } from "./helpers/environment";
|
||||||
import { validate, type ValidatedOptions } from "./validation/options";
|
import {
|
||||||
|
validate,
|
||||||
|
type ValidatedOptions,
|
||||||
|
type RootMode,
|
||||||
|
} from "./validation/options";
|
||||||
|
|
||||||
import type { ConfigFile, IgnoreFile } from "./files";
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
export default function loadPrivatePartialConfig(
|
||||||
inputOpts: mixed,
|
inputOpts: mixed,
|
||||||
@ -28,9 +62,18 @@ export default function loadPrivatePartialConfig(
|
|||||||
|
|
||||||
const args = inputOpts ? validate("arguments", inputOpts) : {};
|
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 absoluteCwd = path.resolve(cwd);
|
||||||
const absoluteRootDir = path.resolve(absoluteCwd, rootDir);
|
const absoluteRootDir = resolveRootMode(
|
||||||
|
path.resolve(absoluteCwd, rootDir),
|
||||||
|
rootMode,
|
||||||
|
);
|
||||||
|
|
||||||
const context: ConfigContext = {
|
const context: ConfigContext = {
|
||||||
filename:
|
filename:
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import type {
|
|||||||
RootInputSourceMapOption,
|
RootInputSourceMapOption,
|
||||||
NestingPath,
|
NestingPath,
|
||||||
CallerMetadata,
|
CallerMetadata,
|
||||||
|
RootMode,
|
||||||
} from "./options";
|
} from "./options";
|
||||||
|
|
||||||
export type ValidatorSet = {
|
export type ValidatorSet = {
|
||||||
@ -60,6 +61,20 @@ type AccessPath = $ReadOnly<{
|
|||||||
}>;
|
}>;
|
||||||
type GeneralPath = OptionPath | AccessPath;
|
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(
|
export function assertSourceMaps(
|
||||||
loc: OptionPath,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import {
|
|||||||
assertConfigFileSearch,
|
assertConfigFileSearch,
|
||||||
assertBabelrcSearch,
|
assertBabelrcSearch,
|
||||||
assertFunction,
|
assertFunction,
|
||||||
|
assertRootMode,
|
||||||
assertSourceMaps,
|
assertSourceMaps,
|
||||||
assertCompact,
|
assertCompact,
|
||||||
assertSourceType,
|
assertSourceType,
|
||||||
@ -30,6 +31,9 @@ import {
|
|||||||
const ROOT_VALIDATORS: ValidatorSet = {
|
const ROOT_VALIDATORS: ValidatorSet = {
|
||||||
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
|
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
|
||||||
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
|
root: (assertString: Validator<$PropertyType<ValidatedOptions, "root">>),
|
||||||
|
rootMode: (assertRootMode: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "rootMode">,
|
||||||
|
>),
|
||||||
configFile: (assertConfigFileSearch: Validator<
|
configFile: (assertConfigFileSearch: Validator<
|
||||||
$PropertyType<ValidatedOptions, "configFile">,
|
$PropertyType<ValidatedOptions, "configFile">,
|
||||||
>),
|
>),
|
||||||
@ -176,6 +180,7 @@ export type ValidatedOptions = {
|
|||||||
babelrcRoots?: BabelrcSearch,
|
babelrcRoots?: BabelrcSearch,
|
||||||
configFile?: ConfigFileSearch,
|
configFile?: ConfigFileSearch,
|
||||||
root?: string,
|
root?: string,
|
||||||
|
rootMode?: RootMode,
|
||||||
code?: boolean,
|
code?: boolean,
|
||||||
ast?: boolean,
|
ast?: boolean,
|
||||||
inputSourceMap?: RootInputSourceMapOption,
|
inputSourceMap?: RootInputSourceMapOption,
|
||||||
@ -260,6 +265,7 @@ export type SourceMapsOption = boolean | "inline" | "both";
|
|||||||
export type SourceTypeOption = "module" | "script" | "unambiguous";
|
export type SourceTypeOption = "module" | "script" | "unambiguous";
|
||||||
export type CompactOption = boolean | "auto";
|
export type CompactOption = boolean | "auto";
|
||||||
export type RootInputSourceMapOption = {} | boolean;
|
export type RootInputSourceMapOption = {} | boolean;
|
||||||
|
export type RootMode = "root" | "upward" | "upward-optional";
|
||||||
|
|
||||||
export type OptionsSource =
|
export type OptionsSource =
|
||||||
| "arguments"
|
| "arguments"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user