From c526927b46c123253954bdf5e89bdf7bf7dea08e Mon Sep 17 00:00:00 2001 From: Tommy Date: Sun, 25 Dec 2016 21:31:28 -0500 Subject: [PATCH] feat: Use babel's built-in option manager for loading configs (#34) The babel-plugin-module-resolver can now be set into a preset and the eslint plugin will work the same. BREAKING CHANGE: The root config and alias must be relative to the project root, not relative to the babelrc file. --- .babelrc | 5 ++ .gitignore | 2 +- lib/index.js | 72 ---------------- package.json | 13 ++- src/index.js | 82 ++++++++----------- test/.babelrc | 4 +- test/examples/components/sub/envonly/.babelrc | 13 --- test/index.test.js | 28 +++++++ 8 files changed, 82 insertions(+), 137 deletions(-) create mode 100644 .babelrc delete mode 100644 lib/index.js delete mode 100644 test/examples/components/sub/envonly/.babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..a9b84b6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["transform-object-rest-spread", { "useBuiltIns": true }] + ] +} diff --git a/.gitignore b/.gitignore index ad7fe3b..84c78ea 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ node_modules/ npm-debug.log coverage/ -.nyc_output +lib/ diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index c6fde25..0000000 --- a/lib/index.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; - -const path = require('path'); -const resolve = require('resolve'); -const pkgUp = require('pkg-up'); -const targetPlugin = require('babel-plugin-module-resolver').default; -const mapModule = require('babel-plugin-module-resolver').mapModule; -const OptionManager = require('babel-core').OptionManager; - -function getPlugins(file, target) { - try { - const manager = new OptionManager(); - const result = manager.init({ - babelrc: true, - filename: file - }); - - return result.plugins.filter(plugin => { - const plug = OptionManager.memoisedPlugins.find(item => item.plugin === plugin[0]); - - return plug && plug.container === target; - }); - } catch (err) { - // This error should only occur if something goes wrong with babel's - // internals. Dump it to console so people know what's going on, - // elsewise the error will simply be squelched in the calling code. - console.error('[eslint-import-resolver-babel-module]', err); - console.error('See: https://github.com/tleunen/eslint-import-resolver-babel-module/pull/34'); - return []; - } -} - -function opts(file, config) { - return Object.assign({}, config, { - basedir: path.dirname(file) - }); -} - -exports.interfaceVersion = 2; - -/** - * Find the full path to 'source', given 'file' as a full reference path. - * - * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js' - * @param {string} source - the module to resolve; i.e './some-module' - * @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js' - * @param {object} options - the resolver options - * @return {object} - */ -exports.resolve = (source, file, options) => { - if (resolve.isCore(source)) return { found: true, path: null }; - - const projectRootDir = path.dirname(pkgUp.sync(file)); - - try { - const instances = getPlugins(file, targetPlugin); - - const pluginOpts = instances.reduce((config, plugin) => ({ - cwd: plugin[1] && plugin[1].cwd ? plugin[1].cwd : config.cwd, - root: config.root.concat(plugin[1] && plugin[1].root ? plugin[1].root : []), - alias: Object.assign(config.alias, plugin[1] ? plugin[1].alias : {}) - }), { root: [], alias: {}, cwd: projectRootDir }); - - const src = mapModule(source, file, pluginOpts, path.resolve(pluginOpts.cwd)) || source; - return { - found: true, - path: resolve.sync(src, opts(file, options)) - }; - } catch (e) { - return { found: false }; - } -}; \ No newline at end of file diff --git a/package.json b/package.json index fd363eb..95cc8d5 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "eslint-import-resolver-babel-module", "version": "2.2.1", - "main": "src/index.js", + "main": "lib/index.js", "description": "babel-plugin-module-resolver resolver for eslint-plugin-import", "repository": { "type": "git", "url": "https://github.com/tleunen/eslint-import-resolver-babel-module.git" }, "files": [ - "src" + "lib" ], "author": "Tommy Leunen (https://tommyleunen.com)", "license": "MIT", @@ -29,11 +29,15 @@ "import" ], "dependencies": { - "find-babel-config": "^1.0.1", + "pkg-up": "^1.0.0", "resolve": "^1.2.0" }, "devDependencies": { + "babel-cli": "^6.18.0", + "babel-core": "^6.21.0", + "babel-jest": "^18.0.0", "babel-plugin-module-resolver": "^2.4.0", + "babel-plugin-transform-object-rest-spread": "^6.20.2", "eslint": "^3.12.2", "eslint-config-tleunen": "^1.0.0", "eslint-plugin-import": "^2.2.0", @@ -42,14 +46,17 @@ "standard-version": "^4.0.0" }, "peerDependencies": { + "babel-core": "^6.0.0", "babel-plugin-module-resolver": "^2.4.0" }, "scripts": { "lint": "eslint src test", + "compile": "babel src --out-dir lib", "pretest": "npm run lint", "test": "jest --coverage", "test:suite": "jest", "test:watch": "jest --watch", + "prepublish": "npm run compile", "release": "standard-version" }, "jest": { diff --git a/src/index.js b/src/index.js index 52ad637..d17e5f5 100644 --- a/src/index.js +++ b/src/index.js @@ -2,49 +2,41 @@ const path = require('path'); const resolve = require('resolve'); +const pkgUp = require('pkg-up'); +const targetPlugin = require('babel-plugin-module-resolver').default; const mapModule = require('babel-plugin-module-resolver').mapModule; -const findBabelConfig = require('find-babel-config'); // eslint-disable-line +const OptionManager = require('babel-core').OptionManager; -function findModuleAliasConfig(conf) { - if (conf.plugins) { - return conf.plugins.find(p => p[0] === 'module-resolver' || p[0] === 'babel-plugin-module-resolver'); - } - return null; -} - -function getPluginOpts(config) { - const env = process.env.BABEL_ENV || process.env.NODE_ENV || 'development'; - - if (config) { - const pluginConfig = findModuleAliasConfig(config); +function getPlugins(file, target) { + try { + const manager = new OptionManager(); + const result = manager.init({ + babelrc: true, + filename: file, + }); - if (config.env && config.env[env]) { - const envPluginConfig = findModuleAliasConfig(config.env[env]); - if (envPluginConfig) { - if (pluginConfig) { - return { - root: [].concat(pluginConfig[1].root, envPluginConfig[1].root), - alias: Object.assign({}, pluginConfig[1].alias, envPluginConfig[1].alias), - }; - } - return envPluginConfig[1]; - } - } + return result.plugins.filter((plugin) => { + const plug = OptionManager.memoisedPlugins.find(item => + item.plugin === plugin[0], + ); - if (pluginConfig) { - return pluginConfig[1]; - } + return plug && plug.container === target; + }); + } catch (err) { + // This error should only occur if something goes wrong with babel's + // internals. Dump it to console so people know what's going on, + // elsewise the error will simply be squelched in the calling code. + console.error('[eslint-import-resolver-babel-module]', err); + console.error('See: https://github.com/tleunen/eslint-import-resolver-babel-module/pull/34'); + return []; } - - return {}; } function opts(file, config) { - return Object.assign( - {}, - config, - { basedir: path.dirname(file) }, - ); + return { + ...config, + basedir: path.dirname(file), + }; } exports.interfaceVersion = 2; @@ -61,20 +53,18 @@ exports.interfaceVersion = 2; exports.resolve = (source, file, options) => { if (resolve.isCore(source)) return { found: true, path: null }; - const babelConfig = findBabelConfig.sync(path.dirname(file)); - const babelrcPath = babelConfig.file; - const config = babelConfig.config; - let cwd = babelrcPath - ? path.dirname(babelrcPath) - : process.cwd(); + const projectRootDir = path.dirname(pkgUp.sync(file)); try { - const pluginOpts = getPluginOpts(config); - if (pluginOpts.cwd !== 'babelrc') { - cwd = pluginOpts.cwd || cwd; - } + const instances = getPlugins(file, targetPlugin); + + const pluginOpts = instances.reduce((config, plugin) => ({ + cwd: plugin[1] && plugin[1].cwd ? plugin[1].cwd : config.cwd, + root: config.root.concat(plugin[1] && plugin[1].root ? plugin[1].root : []), + alias: Object.assign(config.alias, plugin[1] ? plugin[1].alias : {}), + }), { root: [], alias: {}, cwd: projectRootDir }); - const src = mapModule(source, file, pluginOpts, cwd) || source; + const src = mapModule(source, file, pluginOpts, path.resolve(pluginOpts.cwd)) || source; return { found: true, path: resolve.sync(src, opts(file, options)), diff --git a/test/.babelrc b/test/.babelrc index 67b6a16..a538006 100644 --- a/test/.babelrc +++ b/test/.babelrc @@ -2,7 +2,7 @@ "plugins": [ ["module-resolver", { "alias": { - "components": "./examples/components", + "components": "./test/examples/components", "underscore": "npm:lodash" } }] @@ -12,7 +12,7 @@ "plugins": [ ["babel-plugin-module-resolver", { "alias": { - "subsub": "./examples/components/sub/sub" + "subsub": "./test/examples/components/sub/sub" } }] ] diff --git a/test/examples/components/sub/envonly/.babelrc b/test/examples/components/sub/envonly/.babelrc deleted file mode 100644 index e9880c8..0000000 --- a/test/examples/components/sub/envonly/.babelrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "env": { - "test": { - "plugins": [ - ["module-resolver", { - "alias": { - "subsub": "../sub" - } - }] - ] - } - } -} diff --git a/test/index.test.js b/test/index.test.js index 30070a9..e7ca434 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -3,6 +3,7 @@ 'use strict'; const path = require('path'); +const OptionManager = require('babel-core').OptionManager; const resolverPlugin = require('../src/index'); const opts = {}; @@ -134,4 +135,31 @@ describe('eslint-import-resolver-module-resolver', () => { }); }); }); + + describe('babel internals', () => { + let oldInit; + let error; + + beforeEach(() => { + oldInit = OptionManager.prototype.init; + error = console.error; + }); + afterEach(() => { + OptionManager.prototype.init = oldInit; + console.error = error; + }); + + it('should survive babel blowing up', () => { + console.error = jest.fn(); + + OptionManager.prototype.init = undefined; + + expect(resolverPlugin.resolve('underscore', path.resolve('./test/examples/file1'), opts)) + .toEqual({ + found: false, + }); + + expect(console.error).toBeCalled(); + }); + }); });