feat(errors): validate preset when filename is absent (#10181)
* feat(errors): validate preset when filename is absent Closes #10154 * fix: test overrides for filename compulsory * docs: rewrite validate error message per https://github.com/babel/babel/pull/10181#discussion_r301607986 * polish error message
This commit is contained in:
parent
3e4889d649
commit
8da9d8b4b8
@ -18,6 +18,7 @@ import { validatePluginObject } from "./validation/plugins";
|
|||||||
import makeAPI from "./helpers/config-api";
|
import makeAPI from "./helpers/config-api";
|
||||||
|
|
||||||
import loadPrivatePartialConfig from "./partial";
|
import loadPrivatePartialConfig from "./partial";
|
||||||
|
import type { ValidatedOptions } from "./validation/options";
|
||||||
|
|
||||||
type LoadedDescriptor = {
|
type LoadedDescriptor = {
|
||||||
value: {},
|
value: {},
|
||||||
@ -278,6 +279,42 @@ const instantiatePlugin = makeWeakCache(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const validateIfOptionNeedsFilename = (
|
||||||
|
options: ValidatedOptions,
|
||||||
|
descriptor: UnloadedDescriptor,
|
||||||
|
): void => {
|
||||||
|
if (options.test || options.include || options.exclude) {
|
||||||
|
const formattedPresetName = descriptor.name
|
||||||
|
? `"${descriptor.name}"`
|
||||||
|
: "/* your preset */";
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`Preset ${formattedPresetName} requires a filename to be set when babel is called directly,`,
|
||||||
|
`\`\`\``,
|
||||||
|
`babel.transform(code, { filename: 'file.ts', presets: [${formattedPresetName}] });`,
|
||||||
|
`\`\`\``,
|
||||||
|
`See https://babeljs.io/docs/en/options#filename for more information.`,
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const validatePreset = (
|
||||||
|
preset: PresetInstance,
|
||||||
|
context: ConfigContext,
|
||||||
|
descriptor: UnloadedDescriptor,
|
||||||
|
): void => {
|
||||||
|
if (!context.filename) {
|
||||||
|
const { options } = preset;
|
||||||
|
validateIfOptionNeedsFilename(options, descriptor);
|
||||||
|
if (options.overrides) {
|
||||||
|
options.overrides.forEach(overrideOptions =>
|
||||||
|
validateIfOptionNeedsFilename(overrideOptions, descriptor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a config object that will act as the root of a new nested config.
|
* Generate a config object that will act as the root of a new nested config.
|
||||||
*/
|
*/
|
||||||
@ -285,10 +322,9 @@ const loadPresetDescriptor = (
|
|||||||
descriptor: UnloadedDescriptor,
|
descriptor: UnloadedDescriptor,
|
||||||
context: ConfigContext,
|
context: ConfigContext,
|
||||||
): ConfigChain | null => {
|
): ConfigChain | null => {
|
||||||
return buildPresetChain(
|
const preset = instantiatePreset(loadDescriptor(descriptor, context));
|
||||||
instantiatePreset(loadDescriptor(descriptor, context)),
|
validatePreset(preset, context, descriptor);
|
||||||
context,
|
return buildPresetChain(preset, context);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const instantiatePreset = makeWeakCache(
|
const instantiatePreset = makeWeakCache(
|
||||||
|
|||||||
@ -1049,5 +1049,27 @@ describe("buildConfigChain", function() {
|
|||||||
loadOptions({ filename, cwd: path.dirname(filename) }),
|
loadOptions({ filename, cwd: path.dirname(filename) }),
|
||||||
).toThrow(/Error while parsing JSON - /);
|
).toThrow(/Error while parsing JSON - /);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should throw when `test` presents but `filename` is not passed", () => {
|
||||||
|
expect(() => loadOptions({ test: /\.ts$/, plugins: [] })).toThrow(
|
||||||
|
/Configuration contains string\/RegExp pattern/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw when `preset` requires `filename` but it was not passed", () => {
|
||||||
|
expect(() => {
|
||||||
|
loadOptions({
|
||||||
|
presets: [require("./fixtures/config-loading/preset4")],
|
||||||
|
});
|
||||||
|
}).toThrow(/Preset \/\* your preset \*\/ requires a filename/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw when `preset.overrides` requires `filename` but it was not passed", () => {
|
||||||
|
expect(() => {
|
||||||
|
loadOptions({
|
||||||
|
presets: [require("./fixtures/config-loading/preset5")],
|
||||||
|
});
|
||||||
|
}).toThrow(/Preset \/\* your preset \*\/ requires a filename/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
6
packages/babel-core/test/fixtures/config-loading/preset4.js
vendored
Normal file
6
packages/babel-core/test/fixtures/config-loading/preset4.js
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function() {
|
||||||
|
return {
|
||||||
|
test: /\.ts$/,
|
||||||
|
plugins: []
|
||||||
|
}
|
||||||
|
};
|
||||||
8
packages/babel-core/test/fixtures/config-loading/preset5.js
vendored
Normal file
8
packages/babel-core/test/fixtures/config-loading/preset5.js
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module.exports = function() {
|
||||||
|
return {
|
||||||
|
overrides: [{
|
||||||
|
test: /\.ts$/,
|
||||||
|
plugins: []
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user