Take top-level config source into consideration when processing nested env/overrides. (#8493)
This commit is contained in:
parent
ef68114d67
commit
c2a2e24965
@ -13,16 +13,54 @@ import type {
|
|||||||
SourceTypeOption,
|
SourceTypeOption,
|
||||||
CompactOption,
|
CompactOption,
|
||||||
RootInputSourceMapOption,
|
RootInputSourceMapOption,
|
||||||
|
NestingPath,
|
||||||
} from "./options";
|
} from "./options";
|
||||||
|
|
||||||
export type ValidatorSet = {
|
export type ValidatorSet = {
|
||||||
[string]: Validator<any>,
|
[string]: Validator<any>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Validator<T> = (string, mixed) => T;
|
export type Validator<T> = (OptionPath, mixed) => T;
|
||||||
|
|
||||||
|
export function msg(loc: NestingPath | GeneralPath) {
|
||||||
|
switch (loc.type) {
|
||||||
|
case "root":
|
||||||
|
return ``;
|
||||||
|
case "env":
|
||||||
|
return `${msg(loc.parent)}.env["${loc.name}"]`;
|
||||||
|
case "overrides":
|
||||||
|
return `${msg(loc.parent)}.overrides[${loc.index}]`;
|
||||||
|
case "option":
|
||||||
|
return `${msg(loc.parent)}.${loc.name}`;
|
||||||
|
case "access":
|
||||||
|
return `${msg(loc.parent)}[${JSON.stringify(loc.name)}]`;
|
||||||
|
default:
|
||||||
|
throw new Error(`Assertion failure: Unknown type ${loc.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function access(loc: GeneralPath, name: string | number): AccessPath {
|
||||||
|
return {
|
||||||
|
type: "access",
|
||||||
|
name,
|
||||||
|
parent: loc,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OptionPath = $ReadOnly<{
|
||||||
|
type: "option",
|
||||||
|
name: string,
|
||||||
|
parent: NestingPath,
|
||||||
|
}>;
|
||||||
|
type AccessPath = $ReadOnly<{
|
||||||
|
type: "access",
|
||||||
|
name: string | number,
|
||||||
|
parent: GeneralPath,
|
||||||
|
}>;
|
||||||
|
type GeneralPath = OptionPath | AccessPath;
|
||||||
|
|
||||||
export function assertSourceMaps(
|
export function assertSourceMaps(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): SourceMapsOption | void {
|
): SourceMapsOption | void {
|
||||||
if (
|
if (
|
||||||
@ -32,21 +70,24 @@ export function assertSourceMaps(
|
|||||||
value !== "both"
|
value !== "both"
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} must be a boolean, "inline", "both", or undefined`,
|
`${msg(loc)} must be a boolean, "inline", "both", or undefined`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertCompact(key: string, value: mixed): CompactOption | void {
|
export function assertCompact(
|
||||||
|
loc: OptionPath,
|
||||||
|
value: mixed,
|
||||||
|
): CompactOption | void {
|
||||||
if (value !== undefined && typeof value !== "boolean" && value !== "auto") {
|
if (value !== undefined && typeof value !== "boolean" && value !== "auto") {
|
||||||
throw new Error(`.${key} must be a boolean, "auto", or undefined`);
|
throw new Error(`${msg(loc)} must be a boolean, "auto", or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertSourceType(
|
export function assertSourceType(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): SourceTypeOption | void {
|
): SourceTypeOption | void {
|
||||||
if (
|
if (
|
||||||
@ -56,14 +97,14 @@ export function assertSourceType(
|
|||||||
value !== "unambiguous"
|
value !== "unambiguous"
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} must be "module", "script", "unambiguous", or undefined`,
|
`${msg(loc)} must be "module", "script", "unambiguous", or undefined`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertInputSourceMap(
|
export function assertInputSourceMap(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): RootInputSourceMapOption | void {
|
): RootInputSourceMapOption | void {
|
||||||
if (
|
if (
|
||||||
@ -71,75 +112,82 @@ export function assertInputSourceMap(
|
|||||||
typeof value !== "boolean" &&
|
typeof value !== "boolean" &&
|
||||||
(typeof value !== "object" || !value)
|
(typeof value !== "object" || !value)
|
||||||
) {
|
) {
|
||||||
throw new Error(".inputSourceMap must be a boolean, object, or undefined");
|
throw new Error(`${msg(loc)} must be a boolean, object, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertString(key: string, value: mixed): string | void {
|
export function assertString(loc: GeneralPath, value: mixed): string | void {
|
||||||
if (value !== undefined && typeof value !== "string") {
|
if (value !== undefined && typeof value !== "string") {
|
||||||
throw new Error(`.${key} must be a string, or undefined`);
|
throw new Error(`${msg(loc)} must be a string, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertFunction(key: string, value: mixed): Function | void {
|
export function assertFunction(
|
||||||
|
loc: GeneralPath,
|
||||||
|
value: mixed,
|
||||||
|
): Function | void {
|
||||||
if (value !== undefined && typeof value !== "function") {
|
if (value !== undefined && typeof value !== "function") {
|
||||||
throw new Error(`.${key} must be a function, or undefined`);
|
throw new Error(`${msg(loc)} must be a function, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertBoolean(key: string, value: mixed): boolean | void {
|
export function assertBoolean(loc: GeneralPath, value: mixed): boolean | void {
|
||||||
if (value !== undefined && typeof value !== "boolean") {
|
if (value !== undefined && typeof value !== "boolean") {
|
||||||
throw new Error(`.${key} must be a boolean, or undefined`);
|
throw new Error(`${msg(loc)} must be a boolean, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertObject(key: string, value: mixed): {} | void {
|
export function assertObject(loc: GeneralPath, value: mixed): {} | void {
|
||||||
if (
|
if (
|
||||||
value !== undefined &&
|
value !== undefined &&
|
||||||
(typeof value !== "object" || Array.isArray(value) || !value)
|
(typeof value !== "object" || Array.isArray(value) || !value)
|
||||||
) {
|
) {
|
||||||
throw new Error(`.${key} must be an object, or undefined`);
|
throw new Error(`${msg(loc)} must be an object, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertArray(key: string, value: mixed): ?$ReadOnlyArray<mixed> {
|
export function assertArray(
|
||||||
|
loc: GeneralPath,
|
||||||
|
value: mixed,
|
||||||
|
): ?$ReadOnlyArray<mixed> {
|
||||||
if (value != null && !Array.isArray(value)) {
|
if (value != null && !Array.isArray(value)) {
|
||||||
throw new Error(`.${key} must be an array, or undefined`);
|
throw new Error(`${msg(loc)} must be an array, or undefined`);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertIgnoreList(key: string, value: mixed): IgnoreList | void {
|
export function assertIgnoreList(
|
||||||
const arr = assertArray(key, value);
|
loc: OptionPath,
|
||||||
|
value: mixed,
|
||||||
|
): IgnoreList | void {
|
||||||
|
const arr = assertArray(loc, value);
|
||||||
if (arr) {
|
if (arr) {
|
||||||
arr.forEach((item, i) => assertIgnoreItem(key, i, item));
|
arr.forEach((item, i) => assertIgnoreItem(access(loc, i), item));
|
||||||
}
|
}
|
||||||
return (arr: any);
|
return (arr: any);
|
||||||
}
|
}
|
||||||
function assertIgnoreItem(
|
function assertIgnoreItem(loc: GeneralPath, value: mixed): IgnoreItem {
|
||||||
key: string,
|
|
||||||
index: number,
|
|
||||||
value: mixed,
|
|
||||||
): IgnoreItem {
|
|
||||||
if (
|
if (
|
||||||
typeof value !== "string" &&
|
typeof value !== "string" &&
|
||||||
typeof value !== "function" &&
|
typeof value !== "function" &&
|
||||||
!(value instanceof RegExp)
|
!(value instanceof RegExp)
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key}[${index}] must be an array of string/Funtion/RegExp values, or undefined`,
|
`${msg(
|
||||||
|
loc,
|
||||||
|
)} must be an array of string/Funtion/RegExp values, or undefined`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertConfigApplicableTest(
|
export function assertConfigApplicableTest(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): ConfigApplicableTest | void {
|
): ConfigApplicableTest | void {
|
||||||
if (value === undefined) return value;
|
if (value === undefined) return value;
|
||||||
@ -147,12 +195,14 @@ export function assertConfigApplicableTest(
|
|||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach((item, i) => {
|
value.forEach((item, i) => {
|
||||||
if (!checkValidTest(item)) {
|
if (!checkValidTest(item)) {
|
||||||
throw new Error(`.${key}[${i}] must be a string/Function/RegExp.`);
|
throw new Error(
|
||||||
|
`${msg(access(loc, i))} must be a string/Function/RegExp.`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (!checkValidTest(value)) {
|
} else if (!checkValidTest(value)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} must be a string/Function/RegExp, or an array of those`,
|
`${msg(loc)} must be a string/Function/RegExp, or an array of those`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (value: any);
|
return (value: any);
|
||||||
@ -167,7 +217,7 @@ function checkValidTest(value: mixed): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function assertConfigFileSearch(
|
export function assertConfigFileSearch(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): ConfigFileSearch | void {
|
): ConfigFileSearch | void {
|
||||||
if (
|
if (
|
||||||
@ -176,7 +226,7 @@ export function assertConfigFileSearch(
|
|||||||
typeof value !== "string"
|
typeof value !== "string"
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} must be a undefined, a boolean, a string, ` +
|
`${msg(loc)} must be a undefined, a boolean, a string, ` +
|
||||||
`got ${JSON.stringify(value)}`,
|
`got ${JSON.stringify(value)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -185,7 +235,7 @@ export function assertConfigFileSearch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function assertBabelrcSearch(
|
export function assertBabelrcSearch(
|
||||||
key: string,
|
loc: OptionPath,
|
||||||
value: mixed,
|
value: mixed,
|
||||||
): BabelrcSearch | void {
|
): BabelrcSearch | void {
|
||||||
if (value === undefined || typeof value === "boolean") return value;
|
if (value === undefined || typeof value === "boolean") return value;
|
||||||
@ -193,44 +243,43 @@ export function assertBabelrcSearch(
|
|||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
value.forEach((item, i) => {
|
value.forEach((item, i) => {
|
||||||
if (!checkValidTest(item)) {
|
if (!checkValidTest(item)) {
|
||||||
throw new Error(`.${key}[${i}] must be a string/Function/RegExp.`);
|
throw new Error(
|
||||||
|
`${msg(access(loc, i))} must be a string/Function/RegExp.`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (!checkValidTest(value)) {
|
} else if (!checkValidTest(value)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} must be a undefined, a boolean, a string/Function/RegExp ` +
|
`${msg(loc)} must be a undefined, a boolean, a string/Function/RegExp ` +
|
||||||
`or an array of those, got ${JSON.stringify(value)}`,
|
`or an array of those, got ${JSON.stringify(value)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (value: any);
|
return (value: any);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertPluginList(key: string, value: mixed): PluginList | void {
|
export function assertPluginList(
|
||||||
const arr = assertArray(key, value);
|
loc: OptionPath,
|
||||||
|
value: mixed,
|
||||||
|
): PluginList | void {
|
||||||
|
const arr = assertArray(loc, value);
|
||||||
if (arr) {
|
if (arr) {
|
||||||
// Loop instead of using `.map` in order to preserve object identity
|
// Loop instead of using `.map` in order to preserve object identity
|
||||||
// for plugin array for use during config chain processing.
|
// for plugin array for use during config chain processing.
|
||||||
arr.forEach((item, i) => assertPluginItem(key, i, item));
|
arr.forEach((item, i) => assertPluginItem(access(loc, i), item));
|
||||||
}
|
}
|
||||||
return (arr: any);
|
return (arr: any);
|
||||||
}
|
}
|
||||||
function assertPluginItem(
|
function assertPluginItem(loc: GeneralPath, value: mixed): PluginItem {
|
||||||
key: string,
|
|
||||||
index: number,
|
|
||||||
value: mixed,
|
|
||||||
): PluginItem {
|
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
throw new Error(`.${key}[${index}] must include an object`);
|
throw new Error(`${msg(loc)} must include an object`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.length > 3) {
|
if (value.length > 3) {
|
||||||
throw new Error(
|
throw new Error(`${msg(loc)} may only be a two-tuple or three-tuple`);
|
||||||
`.${key}[${index}] may only be a two-tuple or three-tuple`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assertPluginTarget(key, index, true, value[0]);
|
assertPluginTarget(access(loc, 0), value[0]);
|
||||||
|
|
||||||
if (value.length > 1) {
|
if (value.length > 1) {
|
||||||
const opts = value[1];
|
const opts = value[1];
|
||||||
@ -240,38 +289,31 @@ function assertPluginItem(
|
|||||||
(typeof opts !== "object" || Array.isArray(opts))
|
(typeof opts !== "object" || Array.isArray(opts))
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key}[${index}][1] must be an object, false, or undefined`,
|
`${msg(access(loc, 1))} must be an object, false, or undefined`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.length === 3) {
|
if (value.length === 3) {
|
||||||
const name = value[2];
|
const name = value[2];
|
||||||
if (name !== undefined && typeof name !== "string") {
|
if (name !== undefined && typeof name !== "string") {
|
||||||
throw new Error(`.${key}[${index}][2] must be a string, or undefined`);
|
throw new Error(
|
||||||
|
`${msg(access(loc, 2))} must be a string, or undefined`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertPluginTarget(key, index, false, value);
|
assertPluginTarget(loc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (value: any);
|
return (value: any);
|
||||||
}
|
}
|
||||||
function assertPluginTarget(
|
function assertPluginTarget(loc: GeneralPath, value: mixed): PluginTarget {
|
||||||
key: string,
|
|
||||||
index: number,
|
|
||||||
inArray: boolean,
|
|
||||||
value: mixed,
|
|
||||||
): PluginTarget {
|
|
||||||
if (
|
if (
|
||||||
(typeof value !== "object" || !value) &&
|
(typeof value !== "object" || !value) &&
|
||||||
typeof value !== "string" &&
|
typeof value !== "string" &&
|
||||||
typeof value !== "function"
|
typeof value !== "function"
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(`${msg(loc)} must be a string, object, function`);
|
||||||
`.${key}[${index}]${
|
|
||||||
inArray ? `[0]` : ""
|
|
||||||
} must be a string, object, function`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import Plugin from "../plugin";
|
|||||||
|
|
||||||
import removed from "./removed";
|
import removed from "./removed";
|
||||||
import {
|
import {
|
||||||
|
msg,
|
||||||
|
access,
|
||||||
assertString,
|
assertString,
|
||||||
assertBoolean,
|
assertBoolean,
|
||||||
assertObject,
|
assertObject,
|
||||||
@ -21,6 +23,7 @@ import {
|
|||||||
assertSourceType,
|
assertSourceType,
|
||||||
type ValidatorSet,
|
type ValidatorSet,
|
||||||
type Validator,
|
type Validator,
|
||||||
|
type OptionPath,
|
||||||
} from "./option-assertions";
|
} from "./option-assertions";
|
||||||
|
|
||||||
const ROOT_VALIDATORS: ValidatorSet = {
|
const ROOT_VALIDATORS: ValidatorSet = {
|
||||||
@ -248,24 +251,62 @@ 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 OptionsType =
|
export type OptionsSource =
|
||||||
| "arguments"
|
| "arguments"
|
||||||
| "env"
|
|
||||||
| "preset"
|
|
||||||
| "override"
|
|
||||||
| "configfile"
|
| "configfile"
|
||||||
| "babelrcfile"
|
| "babelrcfile"
|
||||||
| "extendsfile";
|
| "extendsfile"
|
||||||
|
| "preset";
|
||||||
|
|
||||||
|
type RootPath = $ReadOnly<{
|
||||||
|
type: "root",
|
||||||
|
source: OptionsSource,
|
||||||
|
}>;
|
||||||
|
type OverridesPath = $ReadOnly<{
|
||||||
|
type: "overrides",
|
||||||
|
index: number,
|
||||||
|
parent: RootPath,
|
||||||
|
}>;
|
||||||
|
type EnvPath = $ReadOnly<{
|
||||||
|
type: "env",
|
||||||
|
name: string,
|
||||||
|
parent: RootPath | OverridesPath,
|
||||||
|
}>;
|
||||||
|
export type NestingPath = RootPath | OverridesPath | EnvPath;
|
||||||
|
|
||||||
|
function getSource(loc: NestingPath): OptionsSource {
|
||||||
|
return loc.type === "root" ? loc.source : getSource(loc.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validate(type: OptionsSource, opts: {}): ValidatedOptions {
|
||||||
|
return validateNested(
|
||||||
|
{
|
||||||
|
type: "root",
|
||||||
|
source: type,
|
||||||
|
},
|
||||||
|
opts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateNested(loc: NestingPath, opts: {}) {
|
||||||
|
const type = getSource(loc);
|
||||||
|
|
||||||
export function validate(type: OptionsType, opts: {}): ValidatedOptions {
|
|
||||||
assertNoDuplicateSourcemap(opts);
|
assertNoDuplicateSourcemap(opts);
|
||||||
|
|
||||||
Object.keys(opts).forEach(key => {
|
Object.keys(opts).forEach(key => {
|
||||||
|
const optLoc = {
|
||||||
|
type: "option",
|
||||||
|
name: key,
|
||||||
|
parent: loc,
|
||||||
|
};
|
||||||
|
|
||||||
if (type === "preset" && NONPRESET_VALIDATORS[key]) {
|
if (type === "preset" && NONPRESET_VALIDATORS[key]) {
|
||||||
throw new Error(`.${key} is not allowed in preset options`);
|
throw new Error(`${msg(optLoc)} is not allowed in preset options`);
|
||||||
}
|
}
|
||||||
if (type !== "arguments" && ROOT_VALIDATORS[key]) {
|
if (type !== "arguments" && ROOT_VALIDATORS[key]) {
|
||||||
throw new Error(`.${key} is only allowed in root programmatic options`);
|
throw new Error(
|
||||||
|
`${msg(optLoc)} is only allowed in root programmatic options`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type !== "arguments" &&
|
type !== "arguments" &&
|
||||||
@ -274,48 +315,47 @@ export function validate(type: OptionsType, opts: {}): ValidatedOptions {
|
|||||||
) {
|
) {
|
||||||
if (type === "babelrcfile" || type === "extendsfile") {
|
if (type === "babelrcfile" || type === "extendsfile") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} is not allowed in .babelrc or "extend"ed files, only in root programmatic options, ` +
|
`${msg(
|
||||||
|
optLoc,
|
||||||
|
)} is not allowed in .babelrc or "extends"ed files, only in root programmatic options, ` +
|
||||||
`or babel.config.js/config file options`,
|
`or babel.config.js/config file options`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key} is only allowed in root programmatic options, or babel.config.js/config file options`,
|
`${msg(
|
||||||
|
optLoc,
|
||||||
|
)} is only allowed in root programmatic options, or babel.config.js/config file options`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (type === "env" && key === "env") {
|
|
||||||
throw new Error(`.${key} is not allowed inside another env block`);
|
|
||||||
}
|
|
||||||
if (type === "env" && key === "overrides") {
|
|
||||||
throw new Error(`.${key} is not allowed inside an env block`);
|
|
||||||
}
|
|
||||||
if (type === "override" && key === "overrides") {
|
|
||||||
throw new Error(`.${key} is not allowed inside an overrides block`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const validator =
|
const validator =
|
||||||
COMMON_VALIDATORS[key] ||
|
COMMON_VALIDATORS[key] ||
|
||||||
NONPRESET_VALIDATORS[key] ||
|
NONPRESET_VALIDATORS[key] ||
|
||||||
BABELRC_VALIDATORS[key] ||
|
BABELRC_VALIDATORS[key] ||
|
||||||
ROOT_VALIDATORS[key];
|
ROOT_VALIDATORS[key] ||
|
||||||
|
throwUnknownError;
|
||||||
|
|
||||||
if (validator) validator(key, opts[key]);
|
validator(optLoc, opts[key]);
|
||||||
else throw buildUnknownError(key);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (opts: any);
|
return (opts: any);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUnknownError(key: string) {
|
function throwUnknownError(loc: OptionPath) {
|
||||||
|
const key = loc.name;
|
||||||
|
|
||||||
if (removed[key]) {
|
if (removed[key]) {
|
||||||
const { message, version = 5 } = removed[key];
|
const { message, version = 5 } = removed[key];
|
||||||
|
|
||||||
throw new ReferenceError(
|
throw new ReferenceError(
|
||||||
`Using removed Babel ${version} option: .${key} - ${message}`,
|
`Using removed Babel ${version} option: ${msg(loc)} - ${message}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
const unknownOptErr = `Unknown option: .${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
|
const unknownOptErr = `Unknown option: ${msg(
|
||||||
|
loc,
|
||||||
|
)}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
|
||||||
|
|
||||||
throw new ReferenceError(unknownOptErr);
|
throw new ReferenceError(unknownOptErr);
|
||||||
}
|
}
|
||||||
@ -331,27 +371,53 @@ function assertNoDuplicateSourcemap(opts: {}): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertEnvSet(key: string, value: mixed): EnvSet<ValidatedOptions> {
|
function assertEnvSet(loc: OptionPath, value: mixed): EnvSet<ValidatedOptions> {
|
||||||
const obj = assertObject(key, value);
|
if (loc.parent.type === "env") {
|
||||||
|
throw new Error(`${msg(loc)} is not allowed inside of another .env block`);
|
||||||
|
}
|
||||||
|
const parent: RootPath | OverridesPath = loc.parent;
|
||||||
|
|
||||||
|
const obj = assertObject(loc, value);
|
||||||
if (obj) {
|
if (obj) {
|
||||||
// Validate but don't copy the .env object in order to preserve
|
// Validate but don't copy the .env object in order to preserve
|
||||||
// object identity for use during config chain processing.
|
// object identity for use during config chain processing.
|
||||||
for (const key of Object.keys(obj)) {
|
for (const envName of Object.keys(obj)) {
|
||||||
const env = assertObject(key, obj[key]);
|
const env = assertObject(access(loc, envName), obj[envName]);
|
||||||
if (env) validate("env", env);
|
if (!env) continue;
|
||||||
|
|
||||||
|
const envLoc = {
|
||||||
|
type: "env",
|
||||||
|
name: envName,
|
||||||
|
parent,
|
||||||
|
};
|
||||||
|
validateNested(envLoc, env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (obj: any);
|
return (obj: any);
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertOverridesList(key: string, value: mixed): OverridesList {
|
function assertOverridesList(loc: OptionPath, value: mixed): OverridesList {
|
||||||
const arr = assertArray(key, value);
|
if (loc.parent.type === "env") {
|
||||||
|
throw new Error(`${msg(loc)} is not allowed inside an .env block`);
|
||||||
|
}
|
||||||
|
if (loc.parent.type === "overrides") {
|
||||||
|
throw new Error(`${msg(loc)} is not allowed inside an .overrides block`);
|
||||||
|
}
|
||||||
|
const parent: RootPath = loc.parent;
|
||||||
|
|
||||||
|
const arr = assertArray(loc, value);
|
||||||
if (arr) {
|
if (arr) {
|
||||||
for (const [index, item] of arr.entries()) {
|
for (const [index, item] of arr.entries()) {
|
||||||
const env = assertObject(`${index}`, item);
|
const objLoc = access(loc, index);
|
||||||
if (!env) throw new Error(`.${key}[${index}] must be an object`);
|
const env = assertObject(objLoc, item);
|
||||||
|
if (!env) throw new Error(`${msg(objLoc)} must be an object`);
|
||||||
|
|
||||||
validate("override", env);
|
const overridesLoc = {
|
||||||
|
type: "overrides",
|
||||||
|
index,
|
||||||
|
parent,
|
||||||
|
};
|
||||||
|
validateNested(overridesLoc, env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (arr: any);
|
return (arr: any);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user