diff --git a/package.json b/package.json index 0fcf8830..cec10492 100644 --- a/package.json +++ b/package.json @@ -49,19 +49,19 @@ ], "license": "MIT", "devDependencies": { + "@wessberg/rollup-plugin-ts": "^1.1.61", "@wessberg/scaffold": "^1.0.19", "@wessberg/ts-config": "^0.0.41", - "standard-changelog": "^2.0.11", - "@wessberg/rollup-plugin-ts": "^1.1.59", - "tslint": "^5.18.0", - "prettier": "^1.18.2", - "pretty-quick": "^1.11.1", + "ava": "2.2.0", "husky": "^3.0.0", "np": "^5.0.3", + "prettier": "^1.18.2", + "pretty-quick": "^1.11.1", + "rollup": "^1.17.0", + "standard-changelog": "^2.0.11", "ts-node": "8.3.0", - "typescript": "^3.5.3", - "rollup": "^1.16.7", - "ava": "2.2.0" + "tslint": "^5.18.0", + "typescript": "^3.5.3" }, "dependencies": { "@babel/core": "^7.5.4", @@ -75,11 +75,11 @@ "@babel/preset-env": "^7.5.4", "@babel/runtime": "^7.5.4", "@types/mkdirp": "^0.5.2", - "@types/node": "^12.6.1", + "@types/node": "^12.6.3", "@types/resolve": "0.0.8", "@wessberg/browserslist-generator": "1.0.23", "@wessberg/stringutil": "^1.0.18", - "browserslist": "4.6.2", + "browserslist": "4.6.6", "find-up": "^4.1.0", "magic-string": "^0.25.3", "mkdirp": "^0.5.1", diff --git a/src/constant/constant.ts b/src/constant/constant.ts index 393fb914..c67d79b9 100644 --- a/src/constant/constant.ts +++ b/src/constant/constant.ts @@ -16,6 +16,7 @@ export const SOURCE_MAP_COMMENT_REGEXP = /\n\/\/# sourceMappingURL=.*/g; export const TSLIB_NAME = `tslib${DECLARATION_EXTENSION}`; export const BABEL_RUNTIME_PREFIX_1 = "@babel/runtime/"; export const BABEL_RUNTIME_PREFIX_2 = "babel-runtime/"; +export const BABEL_CONFIG_JS_FILENAME = "babel.config.js"; export const REGENERATOR_RUNTIME_NAME_1 = `${BABEL_RUNTIME_PREFIX_1}regenerator/index.js`; export const REGENERATOR_RUNTIME_NAME_2 = `${BABEL_RUNTIME_PREFIX_2}regenerator/index.js`; diff --git a/src/util/get-babel-config/find-babel-config-options.ts b/src/util/get-babel-config/find-babel-config-options.ts new file mode 100644 index 00000000..31641c7f --- /dev/null +++ b/src/util/get-babel-config/find-babel-config-options.ts @@ -0,0 +1,6 @@ +import {ITypescriptPluginBabelOptions} from "../../plugin/i-typescript-plugin-options"; + +export interface FindBabelConfigOptions { + cwd: string; + babelConfig?: ITypescriptPluginBabelOptions["babelConfig"]; +} diff --git a/src/util/get-babel-config/find-babel-config-result.ts b/src/util/get-babel-config/find-babel-config-result.ts new file mode 100644 index 00000000..d60b989f --- /dev/null +++ b/src/util/get-babel-config/find-babel-config-result.ts @@ -0,0 +1,22 @@ +import {IBabelInputOptions} from "../../plugin/i-babel-options"; + +export interface FindBabelConfigResultBase { + kind: "project" | "relative" | "dict"; +} + +export interface FindBabelConfigDictResult extends FindBabelConfigResultBase { + kind: "dict"; + options: Partial; +} + +export interface FindBabelConfigProjectResult extends FindBabelConfigResultBase { + kind: "project"; + path: string; +} + +export interface FindBabelConfigRelativeResult extends FindBabelConfigResultBase { + kind: "relative"; + path: string; +} + +export type FindBabelConfigResult = FindBabelConfigDictResult | FindBabelConfigProjectResult | FindBabelConfigRelativeResult; diff --git a/src/util/get-babel-config/find-babel-config.ts b/src/util/get-babel-config/find-babel-config.ts new file mode 100644 index 00000000..1dea124f --- /dev/null +++ b/src/util/get-babel-config/find-babel-config.ts @@ -0,0 +1,81 @@ +import {BABEL_CONFIG_JS_FILENAME} from "../../constant/constant"; +import {join} from "path"; +import {FindBabelConfigOptions} from "./find-babel-config-options"; +import {ensureAbsolute} from "../path/path-util"; +import {FindBabelConfigResult} from "./find-babel-config-result"; +import {IBabelInputOptions} from "../../plugin/i-babel-options"; +// @ts-ignore +import {findConfigUpwards, findRelativeConfig} from "@babel/core/lib/config/files/configuration"; +// @ts-ignore +import {findPackageData} from "@babel/core/lib/config/files/package"; + +/** + * Returns true if the given babelConfig is IBabelInputOptions + * @param {FindBabelConfigOptions["babelConfig"]} babelConfig + * @returns {babelConfig is IBabelInputOptions} + */ +export function isBabelInputOptions(babelConfig?: FindBabelConfigOptions["babelConfig"]): babelConfig is Partial { + return babelConfig != null && typeof babelConfig !== "string"; +} + +/** + * Gets a Babel Config based on the given options + * @param {GetBabelConfigOptions} options + * @returns {GetBabelConfigResult} + */ +export function findBabelConfig({babelConfig, cwd}: FindBabelConfigOptions): FindBabelConfigResult | undefined { + // If babel options are provided directly + if (isBabelInputOptions(babelConfig)) { + return { + kind: "dict", + options: babelConfig + }; + } + + // If a config is given, determine its kind from its file name. + if (babelConfig != null) { + // This looks like a .babelrc or .babelrc.js file + if (babelConfig.startsWith(".babel")) { + return { + kind: "relative", + path: ensureAbsolute(cwd, babelConfig) + }; + } + + // This looks like a project-wide config (such as babel.config.js) + else { + return { + kind: "project", + path: ensureAbsolute(cwd, babelConfig) + }; + } + } + + // In all other cases, try to resolve a config. Prioritize project-wide configs such as 'babel.config.js' + // over relative ones such as '.babelrc' + const projectConfigPath = findConfigUpwards(cwd) as string | null; + + // The resolved config will actually be the directory holding the config. + // If it is defined, join the default config name to it + if (projectConfigPath != null) { + return { + kind: "project", + // The resolved config will actually be the directory holding the config. + // If it is defined, join the default config name to it + path: join(projectConfigPath, BABEL_CONFIG_JS_FILENAME) + }; + } + + // If no config have been resolved, it might be possible to resolve a .babelrc or .babelrc.js file + const pkgData = findPackageData(join(cwd, "package.json")); + const relativeConfigResult = findRelativeConfig(pkgData, process.env.NODE_ENV) as {config: {filepath: string} | null} | null; + if (relativeConfigResult != null && relativeConfigResult.config != null) { + return { + kind: "relative", + path: relativeConfigResult.config.filepath + }; + } + + // No config could be resolved + return undefined; +} diff --git a/src/util/get-babel-config/i-get-babel-config-options.ts b/src/util/get-babel-config/get-babel-config-options.ts similarity index 67% rename from src/util/get-babel-config/i-get-babel-config-options.ts rename to src/util/get-babel-config/get-babel-config-options.ts index 7efaf999..09fc3c71 100644 --- a/src/util/get-babel-config/i-get-babel-config-options.ts +++ b/src/util/get-babel-config/get-babel-config-options.ts @@ -1,13 +1,11 @@ -import {ITypescriptPluginBabelOptions} from "../../plugin/i-typescript-plugin-options"; import {IGetForcedBabelOptionsResult} from "../get-forced-babel-options/i-get-forced-babel-options-result"; import {IGetDefaultBabelOptionsResult} from "../get-default-babel-options/i-get-default-babel-options-result"; import {InputOptions} from "rollup"; +import {FindBabelConfigOptions} from "./find-babel-config-options"; -export interface IGetBabelConfigOptions { - cwd: string; +export interface GetBabelConfigOptions extends FindBabelConfigOptions { browserslist: string[] | undefined; rollupInputOptions: InputOptions; - babelConfig?: ITypescriptPluginBabelOptions["babelConfig"]; forcedOptions?: IGetForcedBabelOptionsResult; defaultOptions?: IGetDefaultBabelOptionsResult; } diff --git a/src/util/get-babel-config/i-get-babel-config-result.ts b/src/util/get-babel-config/get-babel-config-result.ts similarity index 82% rename from src/util/get-babel-config/i-get-babel-config-result.ts rename to src/util/get-babel-config/get-babel-config-result.ts index c75a7c20..309cd111 100644 --- a/src/util/get-babel-config/i-get-babel-config-result.ts +++ b/src/util/get-babel-config/get-babel-config-result.ts @@ -1,6 +1,6 @@ import {IBabelConfig} from "../../plugin/i-babel-options"; -export interface IGetBabelConfigResult { +export interface GetBabelConfigResult { config(filename: string): IBabelConfig; minifyConfig: ((filename: string) => IBabelConfig) | undefined; hasMinifyOptions: boolean; diff --git a/src/util/get-babel-config/get-babel-config.ts b/src/util/get-babel-config/get-babel-config.ts index 721ffcb6..f091f4d5 100644 --- a/src/util/get-babel-config/get-babel-config.ts +++ b/src/util/get-babel-config/get-babel-config.ts @@ -1,7 +1,5 @@ -import {IBabelConfigItem, IBabelInputOptions} from "../../plugin/i-babel-options"; -import {IGetBabelConfigOptions} from "./i-get-babel-config-options"; -import {ensureAbsolute, isBabelPluginTransformRuntime, isBabelPresetEnv, isYearlyBabelPreset} from "../path/path-util"; -import {IGetBabelConfigResult} from "./i-get-babel-config-result"; +import {IBabelConfigItem} from "../../plugin/i-babel-options"; +import {isBabelPluginTransformRuntime, isBabelPresetEnv, isYearlyBabelPreset} from "../path/path-util"; import { BABEL_MINIFICATION_BLACKLIST_PLUGIN_NAMES, BABEL_MINIFICATION_BLACKLIST_PRESET_NAMES, @@ -13,18 +11,12 @@ import { } from "../../constant/constant"; // @ts-ignore import {createConfigItem, loadOptions, loadPartialConfig} from "@babel/core"; +import {GetBabelConfigOptions} from "./get-babel-config-options"; +import {GetBabelConfigResult} from "./get-babel-config-result"; +import {findBabelConfig} from "./find-babel-config"; // tslint:disable:no-any -/** - * Returns true if the given babelConfig is IBabelInputOptions - * @param {IGetBabelConfigOptions["babelConfig"]} babelConfig - * @returns {babelConfig is IBabelInputOptions} - */ -export function isBabelInputOptions(babelConfig?: IGetBabelConfigOptions["babelConfig"]): babelConfig is Partial { - return babelConfig != null && typeof babelConfig !== "string"; -} - /** * Combines the given two sets of presets * @param {IBabelConfigItem[]} userItems @@ -101,8 +93,8 @@ function configItemIsAllowedDuringNoMinification({file: {resolved}}: IBabelConfi /** * Gets a Babel Config based on the given options - * @param {IGetBabelConfigOptions} options - * @returns {IGetBabelConfigResult} + * @param {GetBabelConfigOptions} options + * @returns {GetBabelConfigResult} */ export function getBabelConfig({ babelConfig, @@ -111,14 +103,20 @@ export function getBabelConfig({ defaultOptions = {}, browserslist, rollupInputOptions -}: IGetBabelConfigOptions): IGetBabelConfigResult { +}: GetBabelConfigOptions): GetBabelConfigResult { + const resolvedConfig = findBabelConfig({cwd, babelConfig}); + // Load a partial Babel config based on the input options const partialConfig = loadPartialConfig( - isBabelInputOptions(babelConfig) + resolvedConfig != null && resolvedConfig.kind === "dict" ? // If the given babelConfig is an object of input options, use that as the basis for the full config - {...babelConfig, cwd, root: cwd, configFile: false, babelrc: false} + {...resolvedConfig.options, cwd, root: cwd, configFile: false, babelrc: false} : // Load the path to a babel config provided to the plugin if any, otherwise try to resolve it - {cwd, root: cwd, ...(babelConfig != null ? {configFile: ensureAbsolute(cwd, babelConfig)} : {})} + { + cwd, + root: cwd, + ...(resolvedConfig != null ? {configFile: resolvedConfig.path} : {babelrc: true}) + } ); const {options, config} = partialConfig;