Merge pull request #6904 from loganfsmyth/config-merge-prep

Add a 'cwd' option, and misc refactoring and tweaks before simple config merging
This commit is contained in:
Logan Smyth 2017-11-24 22:54:40 -08:00 committed by GitHub
commit 66ee192a7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 43 deletions

View File

@ -39,16 +39,17 @@ type ConfigPart =
}; };
export default function buildConfigChain( export default function buildConfigChain(
cwd: string,
opts: ValidatedOptions, opts: ValidatedOptions,
envName: string, envName: string,
): Array<ConfigItem> | null { ): Array<ConfigItem> | null {
const filename = opts.filename ? path.resolve(opts.filename) : null; const filename = opts.filename ? path.resolve(cwd, opts.filename) : null;
const builder = new ConfigChainBuilder( const builder = new ConfigChainBuilder(
filename ? new LoadedFile(filename) : null, filename ? new LoadedFile(filename) : null,
); );
try { try {
builder.mergeConfigArguments(opts, process.cwd(), envName); builder.mergeConfigArguments(opts, cwd, envName);
// resolve all .babelrc files // resolve all .babelrc files
if (opts.babelrc !== false && filename) { if (opts.babelrc !== false && filename) {

View File

@ -1,5 +1,6 @@
// @flow // @flow
import path from "path";
import * as context from "../index"; import * as context from "../index";
import Plugin, { validatePluginObject } from "./plugin"; import Plugin, { validatePluginObject } from "./plugin";
import merge from "lodash/merge"; import merge from "lodash/merge";
@ -45,36 +46,29 @@ class OptionManager {
* - `loc` is used to point to the original config. * - `loc` is used to point to the original config.
* - `dirname` is used to resolve plugins relative to it. * - `dirname` is used to resolve plugins relative to it.
*/ */
mergeOptions(config: MergeOptions, pass: Array<Plugin>, envName: string) {
mergeOptions(config: MergeOptions, pass?: Array<Plugin>, envName: string) {
const result = loadConfig(config); const result = loadConfig(config);
const plugins = result.plugins.map(descriptor => const plugins = result.plugins.map(descriptor =>
loadPluginDescriptor(descriptor, envName), loadPluginDescriptor(descriptor, envName),
); );
const presets = result.presets.map(descriptor => const presets = result.presets.map(descriptor => ({
loadPresetDescriptor(descriptor, envName), pass: descriptor.ownPass ? [] : pass,
); preset: loadPresetDescriptor(descriptor, envName),
}));
const passPerPreset = config.options.passPerPreset;
pass = pass || this.passes[0];
// resolve presets // resolve presets
if (presets.length > 0) { if (presets.length > 0) {
let presetPasses = null; // The passes are created in the same order as the preset list, but are inserted before any
if (passPerPreset) { // existing additional passes.
presetPasses = presets.map(() => []); this.passes.splice(
// The passes are created in the same order as the preset list, but are inserted before any 1,
// existing additional passes. 0,
this.passes.splice(1, 0, ...presetPasses); ...presets.map(o => o.pass).filter(p => p !== pass),
} );
presets.forEach((presetConfig, i) => { presets.forEach(({ preset, pass }) => {
this.mergeOptions( this.mergeOptions(preset, pass, envName);
presetConfig,
presetPasses ? presetPasses[i] : pass,
envName,
);
}); });
} }
@ -103,14 +97,15 @@ class OptionManager {
init(inputOpts: {}) { init(inputOpts: {}) {
const args = validate("arguments", inputOpts); const args = validate("arguments", inputOpts);
const { envName = getEnv() } = args; const { envName = getEnv(), cwd = "." } = args;
const absoluteCwd = path.resolve(cwd);
const configChain = buildConfigChain(args, envName); const configChain = buildConfigChain(absoluteCwd, args, envName);
if (!configChain) return null; if (!configChain) return null;
try { try {
for (const config of configChain) { for (const config of configChain) {
this.mergeOptions(config, undefined, envName); this.mergeOptions(config, this.passes[0], envName);
} }
} catch (e) { } catch (e) {
// There are a few case where thrown errors will try to annotate themselves multiple times, so // There are a few case where thrown errors will try to annotate themselves multiple times, so
@ -134,6 +129,7 @@ class OptionManager {
.map(plugins => ({ plugins })); .map(plugins => ({ plugins }));
opts.passPerPreset = opts.presets.length > 0; opts.passPerPreset = opts.presets.length > 0;
opts.envName = envName; opts.envName = envName;
opts.cwd = absoluteCwd;
return { return {
options: opts, options: opts,
@ -147,6 +143,7 @@ type BasicDescriptor = {
options: {} | void, options: {} | void,
dirname: string, dirname: string,
alias: string, alias: string,
ownPass?: boolean,
}; };
type LoadedDescriptor = { type LoadedDescriptor = {
@ -177,6 +174,7 @@ const loadConfig = makeWeakCache((config: MergeOptions): {
createDescriptor(preset, loadPreset, config.dirname, { createDescriptor(preset, loadPreset, config.dirname, {
index, index,
alias: config.alias, alias: config.alias,
ownPass: config.options.passPerPreset,
}), }),
); );
@ -320,9 +318,11 @@ function createDescriptor(
{ {
index, index,
alias, alias,
ownPass,
}: { }: {
index: number, index: number,
alias: string, alias: string,
ownPass?: boolean,
}, },
): BasicDescriptor { ): BasicDescriptor {
let options; let options;
@ -363,18 +363,12 @@ function createDescriptor(
); );
} }
if (options != null && typeof options !== "object") {
throw new Error(
"Plugin/Preset options must be an object, null, or undefined",
);
}
options = options || undefined;
return { return {
alias: filepath || `${alias}$${index}`, alias: filepath || `${alias}$${index}`,
value, value,
options, options,
dirname, dirname,
ownPass,
}; };
} }

View File

@ -17,6 +17,7 @@ import {
} from "./option-assertions"; } from "./option-assertions";
const ROOT_VALIDATORS: ValidatorSet = { const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
filename: (assertString: Validator< filename: (assertString: Validator<
$PropertyType<ValidatedOptions, "filename">, $PropertyType<ValidatedOptions, "filename">,
>), >),
@ -128,6 +129,7 @@ const COMMON_VALIDATORS: ValidatorSet = {
export type InputOptions = ValidatedOptions; export type InputOptions = ValidatedOptions;
export type ValidatedOptions = { export type ValidatedOptions = {
cwd?: string,
filename?: string, filename?: string,
filenameRelative?: string, filenameRelative?: string,
babelrc?: boolean, babelrc?: boolean,
@ -206,6 +208,9 @@ export function validate(type: OptionsType, opts: {}): ValidatedOptions {
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(`.${key} is only allowed in root programmatic options`);
} }
if (type === "env" && key === "env") {
throw new Error(`.${key} is not allowed inside another env block`);
}
const validator = const validator =
COMMON_VALIDATORS[key] || COMMON_VALIDATORS[key] ||

View File

@ -296,12 +296,6 @@ describe("api", function() {
development: { development: {
passPerPreset: true, passPerPreset: true,
presets: [pushPreset("argthree"), pushPreset("argfour")], presets: [pushPreset("argthree"), pushPreset("argfour")],
env: {
development: {
passPerPreset: true,
presets: [pushPreset("argfive"), pushPreset("argsix")],
},
},
}, },
}, },
}); });
@ -327,8 +321,6 @@ describe("api", function() {
"fourteen;", "fourteen;",
"fifteen;", "fifteen;",
"sixteen;", "sixteen;",
"argfive;",
"argsix;",
"argthree;", "argthree;",
"argfour;", "argfour;",
"seven;", "seven;",

View File

@ -1,10 +1,14 @@
import assert from "assert"; import assert from "assert";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import buildConfigChain from "../lib/config/build-config-chain"; import buildConfigChainFn from "../lib/config/build-config-chain";
const DEFAULT_ENV = "development"; const DEFAULT_ENV = "development";
function buildConfigChain(opts, envName) {
return buildConfigChainFn(process.cwd(), opts, envName);
}
function fixture() { function fixture() {
const args = [__dirname, "fixtures", "config"]; const args = [__dirname, "fixtures", "config"];
for (let i = 0; i < arguments.length; i++) { for (let i = 0; i < arguments.length; i++) {

View File

@ -1,7 +1,6 @@
{ {
"plugins": [ "plugins": [
"transform-exponentiation-operator", "transform-exponentiation-operator",
"transform-regenerator",
"transform-template-literals", "transform-template-literals",
"transform-literals", "transform-literals",
"transform-arrow-functions", "transform-arrow-functions",