From f9393683779a78081a5d5e2b34812d65c6838257 Mon Sep 17 00:00:00 2001
From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com>
Date: Tue, 27 Nov 2018 09:54:37 -0800
Subject: [PATCH] fix: ignore `babel.config.js` files by default

I assume this file was added as part of babel v7 and is not a direct replacement for `.babelrc`, so we now have to specify both `babelrc` and `configFile` options.
---
 src/CLIEngine.ts                           |  2 +-
 src/InlineTransformer.ts                   | 20 +++++---
 src/transpile-requires.ts                  | 14 ++++--
 test/cli/CLITest.ts                        | 54 ++++++++++++++++++++++
 test/fixtures/babel-config/babel.config.js | 13 ++++++
 test/fixtures/babel-config/index.js        |  1 +
 test/helpers/runCodemodCLI.ts              | 16 ++++++-
 7 files changed, 106 insertions(+), 14 deletions(-)
 create mode 100644 test/fixtures/babel-config/babel.config.js
 create mode 100644 test/fixtures/babel-config/index.js

diff --git a/src/CLIEngine.ts b/src/CLIEngine.ts
index 8fe0948a..f400c558 100644
--- a/src/CLIEngine.ts
+++ b/src/CLIEngine.ts
@@ -76,7 +76,7 @@ export default class CLIEngine {
 
     runner = new TransformRunner(
       sourcesIterator,
-      new InlineTransformer(plugins)
+      new InlineTransformer(plugins, this.config.findBabelConfig)
     );
 
     for await (let result of runner.run()) {
diff --git a/src/InlineTransformer.ts b/src/InlineTransformer.ts
index 70952731..0acd0dcb 100644
--- a/src/InlineTransformer.ts
+++ b/src/InlineTransformer.ts
@@ -1,17 +1,25 @@
-import { transformAsync } from '@babel/core';
+import { transformAsync, TransformOptions } from '@babel/core';
 import { BabelPlugin } from './BabelPluginTypes';
-import Config from './Config';
 import Transformer from './Transformer';
 
 export default class InlineTransformer implements Transformer {
-  constructor(private readonly plugins: Array<BabelPlugin>) {}
+  constructor(
+    private readonly plugins: Array<BabelPlugin>,
+    private readonly findBabelConfig: boolean = false
+  ) {}
 
   async transform(filepath: string, content: string): Promise<string> {
-    let result = await transformAsync(content, {
+    let options: TransformOptions = {
       filename: filepath,
-      babelrc: false,
+      babelrc: this.findBabelConfig,
       plugins: this.plugins
-    });
+    };
+
+    if (!this.findBabelConfig) {
+      options.configFile = this.findBabelConfig;
+    }
+
+    let result = await transformAsync(content, options);
 
     if (!result) {
       throw new Error(`[${filepath}] babel transform returned null`);
diff --git a/src/transpile-requires.ts b/src/transpile-requires.ts
index 8c223d40..45c27ffe 100644
--- a/src/transpile-requires.ts
+++ b/src/transpile-requires.ts
@@ -4,7 +4,7 @@ import { addHook } from 'pirates';
 import buildAllSyntaxPlugin from './AllSyntaxPlugin';
 import { PluginExtensions, TypeScriptExtensions } from './extensions';
 
-let useBabelrc = false;
+let useBabelConfig = false;
 let revert: (() => void) | null = null;
 
 export function hook(code: string, filename: string): string {
@@ -17,13 +17,17 @@ export function hook(code: string, filename: string): string {
   let presets: Array<string> = [];
   let options: TransformOptions = {
     filename,
-    babelrc: useBabelrc,
+    babelrc: useBabelConfig,
     presets: presets,
     plugins: [buildAllSyntaxPlugin('module')],
     sourceMaps: 'inline'
   };
 
-  if (!useBabelrc) {
+  if (!useBabelConfig) {
+    options.configFile = useBabelConfig;
+  }
+
+  if (!useBabelConfig) {
     if (TypeScriptExtensions.has(ext)) {
       presets.push(require.resolve('@babel/preset-typescript'));
     }
@@ -40,9 +44,9 @@ export function hook(code: string, filename: string): string {
   return result.code as string;
 }
 
-export function enable(babelrc: boolean = false) {
+export function enable(shouldUseBabelConfig: boolean = false) {
   disable();
-  useBabelrc = babelrc;
+  useBabelConfig = shouldUseBabelConfig;
   revert = addHook(hook, {
     exts: Array.from(PluginExtensions),
     ignoreNodeModules: true
diff --git a/test/cli/CLITest.ts b/test/cli/CLITest.ts
index b58cbb54..d243418c 100644
--- a/test/cli/CLITest.ts
+++ b/test/cli/CLITest.ts
@@ -557,4 +557,58 @@ describe('CLI', function() {
 
     deepEqual({ status, stdout }, { status: 1, stdout: '' });
   });
+
+  it('ignores babel.config.js files by default', async function() {
+    let workspace = await copyFixturesInto(
+      'babel-config',
+      await createTemporaryDirectory('babel-config')
+    );
+    let { status, stdout, stderr } = await runCodemodCLI(
+      ['index.js'],
+      undefined,
+      workspace
+    );
+
+    strictEqual(
+      await readFile(join(workspace, 'index.js'), 'utf8'),
+      'const a = 1;\n',
+      'file contents should not change'
+    );
+
+    deepEqual(
+      { status, stdout, stderr },
+      {
+        status: 0,
+        stdout: 'index.js\n1 file(s), 0 modified, 0 errors\n',
+        stderr: ''
+      }
+    );
+  });
+
+  it('reads babel.config.js files if requested', async function() {
+    let workspace = await copyFixturesInto(
+      'babel-config',
+      await createTemporaryDirectory('babel-config')
+    );
+    let { status, stdout, stderr } = await runCodemodCLI(
+      ['index.js', '--find-babel-config'],
+      undefined,
+      workspace
+    );
+
+    strictEqual(
+      await readFile(join(workspace, 'index.js'), 'utf8'),
+      '"use strict";\nvar a = 1;\n',
+      'file should have been transpiled'
+    );
+
+    deepEqual(
+      { status, stdout, stderr },
+      {
+        status: 0,
+        stdout: 'index.js\n1 file(s), 1 modified, 0 errors\n',
+        stderr: ''
+      }
+    );
+  });
 });
diff --git a/test/fixtures/babel-config/babel.config.js b/test/fixtures/babel-config/babel.config.js
new file mode 100644
index 00000000..e4551b32
--- /dev/null
+++ b/test/fixtures/babel-config/babel.config.js
@@ -0,0 +1,13 @@
+module.exports = function(api) {
+  api.cache(true);
+  return {
+    presets: [
+      [
+        '@babel/preset-env',
+        {
+          forceAllTransforms: true
+        }
+      ]
+    ]
+  }
+};
diff --git a/test/fixtures/babel-config/index.js b/test/fixtures/babel-config/index.js
new file mode 100644
index 00000000..54b82a09
--- /dev/null
+++ b/test/fixtures/babel-config/index.js
@@ -0,0 +1 @@
+const a = 1;
diff --git a/test/helpers/runCodemodCLI.ts b/test/helpers/runCodemodCLI.ts
index 5321d642..086391e2 100644
--- a/test/helpers/runCodemodCLI.ts
+++ b/test/helpers/runCodemodCLI.ts
@@ -6,7 +6,8 @@ export type CLIResult = { status: number; stdout: string; stderr: string };
 
 export default async function runCodemodCLI(
   args: Array<string>,
-  stdin: string = ''
+  stdin: string = '',
+  cwd?: string
 ): Promise<CLIResult> {
   let stdinStream = new PassThrough();
   let stdoutStream = new PassThrough();
@@ -15,7 +16,18 @@ export default async function runCodemodCLI(
   stdinStream.end(new Buffer(stdin));
 
   let argv = [process.argv[0], require.resolve('../../bin/codemod'), ...args];
-  let status = await run(argv, stdinStream, stdoutStream, stderrStream);
+  let status: number;
+  let oldCwd = process.cwd();
+
+  try {
+    if (cwd) {
+      process.chdir(cwd);
+    }
+
+    status = await run(argv, stdinStream, stdoutStream, stderrStream);
+  } finally {
+    process.chdir(oldCwd);
+  }
 
   stdoutStream.end();
   stderrStream.end();