├── .babelrc ├── .editorconfig ├── .eslintrc.yml ├── .github └── workflows │ └── test.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── codecov.yml ├── package-lock.json ├── package.json ├── src └── index.js └── test ├── .babelrc ├── examples ├── components │ ├── c1.js │ ├── c3.jsx │ ├── customFile.customExt │ └── sub │ │ ├── envonly │ │ └── yo.js │ │ └── sub │ │ └── c2.js ├── file1.js └── monorepo │ └── my-lib │ ├── .babelrc │ ├── package.json │ └── src │ └── item.js └── index.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/env", { 4 | "targets": { 5 | "node": 10 6 | }, 7 | "loose": true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | root: true 2 | 3 | extends: 4 | - "eslint:recommended" 5 | 6 | parserOptions: 7 | ecmaVersion: 2018 8 | sourceType: 'module' 9 | 10 | env: 11 | node: true 12 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x, 18.x, 19.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - name: npm install, and build 24 | run: | 25 | npm ci 26 | npm run build --if-present 27 | env: 28 | CI: true 29 | - name: npm test 30 | run: npm run test:coverage 31 | - name: coverage 32 | uses: codecov/codecov-action@v3 33 | if: matrix.node-version == '19.x' 34 | with: 35 | token: ${{ secrets.CODECOV_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | 5 | coverage/ 6 | lib/ 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [5.3.2](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.3.1...v5.3.2) (2023-01-16) 6 | 7 | ### [5.3.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.3.0...v5.3.1) (2021-04-26) 8 | 9 | 10 | ### Bug Fixes 11 | 12 | * fix npm import ([#118](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/118)) ([0289f28](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/0289f288bb9dea21c3cba9faa346acd5877b18d4)), closes [#117](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/117) 13 | 14 | ## [5.3.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.2.0...v5.3.0) (2021-04-19) 15 | 16 | 17 | ### ⚠ BREAKING CHANGES 18 | 19 | * Now requires Node 10 20 | 21 | ### Features 22 | 23 | * Allow early exit on existing directories ([#115](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/115)) ([f5f205e](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f5f205ea76e7ed31ce650b359ca7cc9d82f72d42)) 24 | 25 | 26 | * Update dev dependencies ([6376546](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/63765467398c4150a707cf3d1b6398d2ed95bbeb)) 27 | 28 | 29 | # [5.2.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.1.2...v5.2.0) (2020-10-19) 30 | 31 | 32 | ### Features 33 | 34 | * Add support for passing `babelOptions` to `OptionsManager#init` ([#113](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/113)) ([c23f28d](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/c23f28d)) 35 | 36 | 37 | 38 | 39 | ## [5.1.2](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.1.1...v5.1.2) (2020-01-23) 40 | 41 | 42 | ### Bug Fixes 43 | 44 | * Add support for custom resolvePath from babel plugin ([#109](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/109)) ([5708051](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/5708051)) 45 | 46 | 47 | 48 | 49 | ## [5.1.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.1.0...v5.1.1) (2020-01-07) 50 | 51 | 52 | 53 | 54 | # [5.1.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.0.1...v5.1.0) (2019-04-25) 55 | 56 | 57 | ### Features 58 | 59 | * Add monorepo support ([#101](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/101)) ([f932339](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f932339)), closes [#100](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/100) 60 | 61 | 62 | 63 | 64 | ## [5.0.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.0.0...v5.0.1) (2019-01-29) 65 | 66 | 67 | ### Bug Fixes 68 | 69 | * Fix bad babel compilation & compile the spread operator with Object.assign ([a2d8712](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/a2d8712)), closes [#98](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/98) 70 | 71 | 72 | 73 | 74 | # [5.0.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.0.0-beta.1...v5.0.0) (2019-01-22) 75 | 76 | 77 | 78 | 79 | # [5.0.0-beta.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v5.0.0-beta.0...v5.0.0-beta.1) (2018-08-14) 80 | 81 | 82 | 83 | 84 | # [5.0.0-beta.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0...v5.0.0-beta.0) (2017-12-11) 85 | 86 | 87 | ### Bug Fixes 88 | 89 | * **babel:** Support latest babel 7 only ([#78](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/78)) ([f2804c5](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f2804c5)) 90 | 91 | 92 | ### BREAKING CHANGES 93 | 94 | * **babel:** This resolver now requires babel 7 95 | 96 | 97 | 98 | 99 | # [4.0.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.5...v4.0.0) (2017-12-11) 100 | 101 | 102 | ### Bug Fixes 103 | 104 | * **babel:** Support only babel 6 ([#80](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/80)) ([f01d29d](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f01d29d)) 105 | 106 | 107 | 108 | 109 | # [4.0.0-beta.5](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2017-10-12) 110 | 111 | 112 | 113 | 114 | # [4.0.0-beta.4](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2017-10-12) 115 | 116 | 117 | ### Features 118 | 119 | * Add support for Babel 7.0.0 ([#63](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/63)) ([1ffa7f5](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/1ffa7f5)) 120 | * Allow the resolver options to be set in the eslint file ([#68](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/68)) ([8ee7c08](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/8ee7c08)) 121 | 122 | 123 | 124 | 125 | # [4.0.0-beta.3](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2017-07-10) 126 | 127 | 128 | ### Bug Fixes 129 | 130 | * Use new resolvePath function from module-resolver 3.0.0-beta.4 ([f731792](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f731792)) 131 | 132 | 133 | 134 | 135 | # [4.0.0-beta.2](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2017-05-17) 136 | 137 | 138 | ### Features 139 | 140 | * Strip the webpack loaders and query string from the source before resolving the file ([#60](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/60)) ([21c37f2](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/21c37f2)), closes [#59](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/59) 141 | 142 | 143 | 144 | 145 | # [4.0.0-beta.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2017-04-25) 146 | 147 | 148 | ### Bug Fixes 149 | 150 | * Fix resolution when using a custom cwd ([#55](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/55)) ([188f338](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/188f338)), closes [#43](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/43) 151 | * Fix the custom babel cwd in an editor ([#56](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/56)) ([b13ffd9](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/b13ffd9)) 152 | 153 | 154 | 155 | 156 | # [4.0.0-beta.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v3.0.0...v4.0.0-beta.0) (2017-04-23) 157 | 158 | 159 | ### Bug Fixes 160 | 161 | * Fix build ([91029b8](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/91029b8)) 162 | * Fix lib to support babel plugin v3 ([#54](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/54)) ([731ab8c](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/731ab8c)) 163 | * Prevents `options.extensions` from failing when `options` is `null` ([#47](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/47)) ([5d297a7](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/5d297a7)) 164 | 165 | 166 | ### BREAKING CHANGES 167 | 168 | * Not compatible with babel-plugin-module-resolver v2.x 169 | 170 | 171 | 172 | 173 | # [3.0.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v2.2.1...v3.0.0) (2017-02-05) 174 | 175 | 176 | ### Bug Fixes 177 | 178 | * Fix support for custom extensions from babel ([#39](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/39)) ([fa885e8](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/fa885e8)) 179 | 180 | 181 | ### Features 182 | 183 | * Use babel's built-in option manager for loading configs ([#34](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/34)) ([c526927](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/c526927)) 184 | 185 | 186 | ### Fix 187 | 188 | * Fix linting when using a root glob config ([#38](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/38)) ([45a78be](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/45a78be)) 189 | 190 | 191 | ### BREAKING CHANGES 192 | 193 | * Now requires babel-plugin-module-resolver >= 2.5.0 194 | * The root config and alias must be relative to the project root, not relative to the babelrc file. 195 | 196 | 197 | 198 | 199 | ## [2.2.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v2.2.0...v2.2.1) (2016-11-11) 200 | 201 | 202 | ### Reverts 203 | 204 | * "Use `babel`'s built-in option manager for loading configs." ([#31](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/31)) ([6d1add0](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/6d1add0)) 205 | 206 | 207 | 208 | 209 | # [2.2.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v2.1.1...v2.2.0) (2016-11-09) 210 | 211 | 212 | ### Features 213 | 214 | * Add support for having the babel plugin configured in a preset ([#28](https://github.com/tleunen/eslint-import-resolver-babel-module/issues/28)) ([952863e](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/952863e)) 215 | 216 | 217 | 218 | 219 | ## [2.1.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v2.1.0...v2.1.1) (2016-11-07) 220 | 221 | 222 | ### Bug Fixes 223 | 224 | * Fix usage of let ([a925e3f](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/a925e3f)) 225 | 226 | 227 | 228 | 229 | # [2.1.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v3.0.0-beta.1...v2.1.0) (2016-11-06) 230 | 231 | 232 | ### Features 233 | 234 | * Add support for the custom cwd option from babel-resolver ([0a0d42c](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/0a0d42c)) 235 | 236 | 237 | 238 | 239 | ## [2.0.1](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v2.0.0...v2.0.1) (2016-08-14) 240 | 241 | 242 | ### Bug Fixes 243 | 244 | * Remove deconstructuring to fix build on Node < 6 ([9649b9a](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/9649b9a)) 245 | 246 | 247 | 248 | 249 | # [2.0.0](https://github.com/tleunen/eslint-import-resolver-babel-module/compare/v1.5.1...v2.0.0) (2016-08-14) 250 | 251 | 252 | ### Features 253 | 254 | * Support for new version of babel-plugin-module-resolver v2 ([f2fc1f3](https://github.com/tleunen/eslint-import-resolver-babel-module/commit/f2fc1f3)) 255 | 256 | 257 | ### BREAKING CHANGES 258 | 259 | * This removes the support for babel-plugin-module-alias v1 260 | 261 | 262 | 263 | 264 | ## [1.5.1](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/compare/v1.5.0...v1.5.1) (2016-08-09) 265 | 266 | 267 | ### Bug Fixes 268 | 269 | * Fix config lookup with specific environment ([50f4f6e](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/commit/50f4f6e)), closes [#22](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/issues/22) 270 | 271 | 272 | 273 | 274 | # [1.5.0](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/compare/v1.4.2...v1.5.0) (2016-08-06) 275 | 276 | 277 | ### Bug Fixes 278 | 279 | * **resolver:** Add cascading support ([#17](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/issues/17)) ([dd94f0a](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/commit/dd94f0a)), closes [#15](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/issues/15) 280 | * Also search config with 'babel-plugin-' prefix name ([c7633d6](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/commit/c7633d6)) 281 | 282 | 283 | ### Features 284 | 285 | * Add "env" support ([#19](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/issues/19)) ([71431bd](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/commit/71431bd)) 286 | 287 | 288 | 289 | 290 | ## [1.4.2](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/compare/v1.4.1...v1.4.2) (2016-07-10) 291 | 292 | 293 | ### Bug Fixes 294 | 295 | * **mapping:** Fix mapping again in editors ([3b3bc98](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/commit/3b3bc98)) 296 | 297 | 298 | 299 | 300 | ## [1.4.1](https://github.com/tleunen/eslint-import-resolver-babel-module-alias/compare/v1.4.0...v1.4.1) (2016-07-10) 301 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tommy Leunen (tommyleunen.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eslint-import-resolver-babel-module 2 | [![npm][npm-version-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coverage Status][coverage-image]][coverage-url] 3 | 4 | A [babel-plugin-module-resolver][babel-plugin-module-resolver] resolver for [eslint-plugin-import][eslint-plugin-import] 5 | 6 | ## Installation 7 | 8 | ```sh 9 | npm install --save-dev eslint-plugin-import eslint-import-resolver-babel-module 10 | ``` 11 | 12 | ## Usage 13 | 14 | Inside your `.eslintrc` file, pass this resolver to `eslint-plugin-import`: 15 | ``` 16 | "settings": { 17 | "import/resolver": { 18 | "babel-module": {} 19 | } 20 | } 21 | ``` 22 | 23 | And see [babel-plugin-module-resolver][babel-plugin-module-resolver] to know how to configure your aliases. 24 | 25 | ### Example 26 | 27 | ```json 28 | { 29 | "extends": "airbnb", 30 | "rules": { 31 | "comma-dangle": 0 32 | }, 33 | "settings": { 34 | "import/resolver": { 35 | "babel-module": {} 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | ## Directory Imports 42 | 43 | Some babel plugins like [babel-plugin-import-directory](https://github.com/Anmo/babel-plugin-import-directory) or [babel-plugin-wildcard](https://github.com/vihanb/babel-plugin-wildcard) allow to import directories (i.e. each file inside a directory) as an object. In order to support this, you can activate the `allowExistingDirectories` option as follows: 44 | 45 | ``` 46 | "settings": { 47 | "import/resolver": { 48 | "babel-module": { allowExistingDirectories: true } 49 | } 50 | } 51 | ``` 52 | 53 | Now when you import a directory like this, the ESLint plugin won't complain and recognize the existing directory: 54 | 55 | ``` 56 | import * as Items from './dir'; 57 | ``` 58 | 59 | ## License 60 | 61 | MIT, see [LICENSE.md](/LICENSE.md) for details. 62 | 63 | 64 | [ci-image]: https://circleci.com/gh/tleunen/eslint-import-resolver-babel-module.svg?style=shield 65 | [ci-url]: https://circleci.com/gh/tleunen/eslint-import-resolver-babel-module 66 | [coverage-image]: https://codecov.io/gh/tleunen/eslint-import-resolver-babel-module/branch/master/graph/badge.svg 67 | [coverage-url]: https://codecov.io/gh/tleunen/eslint-import-resolver-babel-module 68 | [npm-version-image]: https://img.shields.io/npm/v/eslint-import-resolver-babel-module.svg 69 | [npm-url]: https://www.npmjs.com/package/eslint-import-resolver-babel-module 70 | [babel-plugin-module-resolver]: https://github.com/tleunen/babel-plugin-module-resolver 71 | [eslint-plugin-import]: https://github.com/benmosher/eslint-plugin-import 72 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: 2 | layout: "header, tree" 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-import-resolver-babel-module", 3 | "version": "5.3.2", 4 | "main": "lib/index.js", 5 | "description": "babel-plugin-module-resolver resolver for eslint-plugin-import", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tleunen/eslint-import-resolver-babel-module.git" 9 | }, 10 | "engines": { 11 | "node": ">=10.0.0" 12 | }, 13 | "files": [ 14 | "lib" 15 | ], 16 | "author": "Tommy Leunen (https://tommyleunen.com)", 17 | "license": "MIT", 18 | "keywords": [ 19 | "eslint", 20 | "eslint-plugin-import", 21 | "eslint-import-resolver", 22 | "babel", 23 | "babel-plugin", 24 | "module", 25 | "resolver", 26 | "alias", 27 | "rewrite", 28 | "resolve", 29 | "rename", 30 | "mapping", 31 | "require", 32 | "import" 33 | ], 34 | "dependencies": { 35 | "pkg-up": "^3.1.0", 36 | "resolve": "^1.20.0" 37 | }, 38 | "devDependencies": { 39 | "@babel/cli": "^7.13.14", 40 | "@babel/core": "^7.13.15", 41 | "@babel/preset-env": "^7.13.15", 42 | "babel-core": "^7.0.0-0", 43 | "babel-jest": "^26.6.3", 44 | "babel-plugin-module-resolver": "^5.0.0", 45 | "eslint": "^7.24.0", 46 | "jest": "^26.6.3", 47 | "lodash": "^4.17.21", 48 | "standard-version": "^9.2.0" 49 | }, 50 | "peerDependencies": { 51 | "@babel/core": "^7.0.0-0", 52 | "babel-plugin-module-resolver": "^3.0.0 || ^4.0.0 || ^5.0.0" 53 | }, 54 | "scripts": { 55 | "lint": "eslint src test", 56 | "compile": "babel src --out-dir lib", 57 | "pretest": "npm run lint", 58 | "test": "jest", 59 | "test:coverage": "jest --coverage", 60 | "test:watch": "jest --watch", 61 | "prepare": "npm run compile", 62 | "release": "standard-version" 63 | }, 64 | "jest": { 65 | "testEnvironment": "node", 66 | "testRegex": "/test/.*\\.test\\.js$", 67 | "collectCoverageFrom": [ 68 | "src/**/*.js" 69 | ] 70 | }, 71 | "greenkeeper": { 72 | "ignore": [ 73 | "babel-jest", 74 | "eslint", 75 | "eslint-plugin-import" 76 | ] 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const resolve = require('resolve'); 3 | const pkgUp = require('pkg-up'); 4 | const { resolvePath } = require('babel-plugin-module-resolver'); 5 | const { OptionManager } = require('@babel/core'); 6 | const fs = require('fs'); 7 | 8 | function getPlugins(file, cwd, babelOptions) { 9 | try { 10 | const manager = new OptionManager(); 11 | const result = manager.init({ 12 | babelrc: true, 13 | filename: file, 14 | cwd, 15 | ...babelOptions, 16 | }); 17 | 18 | return result.plugins.filter(plugin => plugin.key === 'module-resolver'); 19 | } catch (err) { 20 | // This error should only occur if something goes wrong with babel's 21 | // internals. Dump it to console so people know what's going on, 22 | // elsewise the error will simply be squelched in the calling code. 23 | console.error('[eslint-import-resolver-babel-module]', err); 24 | console.error('See: https://github.com/tleunen/eslint-import-resolver-babel-module/pull/34'); 25 | return []; 26 | } 27 | } 28 | 29 | function getPluginOptions(file, cwd, defaultOptions) { 30 | const instances = getPlugins(file, cwd, defaultOptions.babelOptions); 31 | 32 | return instances.reduce( 33 | (config, plugin) => ({ 34 | cwd: plugin.options.cwd || config.cwd, 35 | root: config.root.concat(plugin.options.root || []), 36 | alias: Object.assign(config.alias, plugin.options.alias || {}), 37 | resolvePath: plugin.options.resolvePath || config.resolvePath, 38 | extensions: plugin.options.extensions || config.extensions, 39 | }), 40 | defaultOptions, 41 | ); 42 | } 43 | 44 | function stripWebpack(src, alias) { 45 | let source = src; 46 | const aliases = Object.keys(alias); 47 | let index = source.length; 48 | aliases.forEach(((element) => { 49 | const i = source.indexOf(element); 50 | if (i >= 0 && i < index) { 51 | index = i; 52 | } 53 | })); 54 | // strip loaders 55 | const finalBang = index ? source.lastIndexOf('!', index - 1) : -1; 56 | if (finalBang >= 0) { 57 | source = source.slice(finalBang + 1); 58 | } 59 | 60 | // strip resource query 61 | const finalQuestionMark = source.lastIndexOf('?'); 62 | if (finalQuestionMark >= 0) { 63 | source = source.slice(0, finalQuestionMark); 64 | } 65 | return source; 66 | } 67 | 68 | exports.interfaceVersion = 2; 69 | 70 | const defaultExtensions = ['.js', '.jsx', '.es', '.es6', '.mjs']; 71 | 72 | /** 73 | * Find the full path to 'source', given 'file' as a full reference path. 74 | * 75 | * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js' 76 | * @param {string} source - the module to resolve; i.e './some-module' 77 | * @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js' 78 | * @param {object} options - the resolver options 79 | * @return {object} 80 | */ 81 | exports.resolve = (source, file, opts) => { 82 | const options = opts || {}; 83 | if (resolve.isCore(source)) return { found: true, path: null }; 84 | 85 | const projectRootDir = path.dirname(pkgUp.sync({cwd: file})); 86 | 87 | try { 88 | const pluginOptions = getPluginOptions( 89 | file, 90 | projectRootDir, 91 | { 92 | // if .babelrc doesn't exist, try to get the configuration information from `options`, 93 | // which gets defined by the eslint configuration file. 94 | // e.g. in .eslintrc file 95 | // "import/resolver": { 96 | // "babel-module": { 97 | // "root": ["./src"], 98 | // "extensions": [".js", ".jsx"] 99 | // } 100 | // } 101 | cwd: options.cwd || projectRootDir, 102 | root: options.root || [], 103 | alias: options.alias || {}, 104 | resolvePath: options.resolvePath, 105 | extensions: options.extensions || defaultExtensions, 106 | babelOptions: options.babelOptions || {}, 107 | }, 108 | ); 109 | 110 | const finalSource = stripWebpack(source, pluginOptions.alias); 111 | const resolvePathFunc = pluginOptions.resolvePath || resolvePath; 112 | const src = resolvePathFunc(finalSource, file, pluginOptions); 113 | if (src) { 114 | const absoluteSrc = path.join(path.dirname(file), src); 115 | 116 | if (options.allowExistingDirectories && fs.existsSync(absoluteSrc)) { 117 | return { found: true, path: absoluteSrc }; 118 | } 119 | } 120 | 121 | const extensions = options.extensions || pluginOptions.extensions; 122 | 123 | return { 124 | found: true, 125 | path: resolve.sync(src || source, { 126 | ...options, 127 | extensions, 128 | basedir: path.dirname(file), 129 | }), 130 | }; 131 | } catch (e) { 132 | return { found: false }; 133 | } 134 | }; 135 | -------------------------------------------------------------------------------- /test/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["module-resolver", { 4 | "root": ["./test/examples/**"], 5 | "alias": { 6 | "components": "./test/examples/components", 7 | "babel-plugin": "babel-plugin-module-resolver", 8 | "!src": "./test/examples/components" 9 | }, 10 | "extensions": [".js", ".customExt"] 11 | }] 12 | ], 13 | "env": { 14 | "testenv": { 15 | "plugins": [ 16 | ["babel-plugin-module-resolver", { 17 | "alias": { 18 | "subsub": "./test/examples/components/sub/sub" 19 | } 20 | }] 21 | ] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/examples/components/c1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/components/c1.js -------------------------------------------------------------------------------- /test/examples/components/c3.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/components/c3.jsx -------------------------------------------------------------------------------- /test/examples/components/customFile.customExt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/components/customFile.customExt -------------------------------------------------------------------------------- /test/examples/components/sub/envonly/yo.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/components/sub/envonly/yo.js -------------------------------------------------------------------------------- /test/examples/components/sub/sub/c2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/components/sub/sub/c2.js -------------------------------------------------------------------------------- /test/examples/file1.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/file1.js -------------------------------------------------------------------------------- /test/examples/monorepo/my-lib/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["module-resolver", { 4 | "alias": { 5 | "~": "./src" 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/examples/monorepo/my-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-lib", 3 | "version": "1.0.0-test.0", 4 | "description": "Imagine a monorepo", 5 | "private": true, 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT" 13 | } 14 | -------------------------------------------------------------------------------- /test/examples/monorepo/my-lib/src/item.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tleunen/eslint-import-resolver-babel-module/8d0434a16927380c08adc2e6e0d8b9708d76ba9a/test/examples/monorepo/my-lib/src/item.js -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | /* eslint-disable strict */ 3 | 4 | 'use strict'; 5 | 6 | const path = require('path'); 7 | const resolverPlugin = require('../src/index'); 8 | 9 | const opts = {}; 10 | const extensionOpts = { extensions: ['.js', '.jsx'] }; 11 | 12 | describe('eslint-import-resolver-module-resolver', () => { 13 | it('should export the interfaceVersion', () => { 14 | expect(resolverPlugin.interfaceVersion).toBeDefined(); 15 | expect(resolverPlugin.interfaceVersion).toBe(2); 16 | }); 17 | 18 | it('should return `true` when mapped to a npm module', () => { 19 | expect(resolverPlugin.resolve('pkg-up', path.resolve('./test/examples/file1'), opts)) 20 | .toEqual({ 21 | found: true, 22 | path: path.resolve(__dirname, '../node_modules/pkg-up/index.js'), 23 | }); 24 | }); 25 | 26 | it('should return `true` when mapped to a file', () => { 27 | expect(resolverPlugin.resolve('components/c1', path.resolve('./test/examples/components/sub/sub/c2.js'), opts)) 28 | .toEqual({ 29 | found: true, 30 | path: path.resolve(__dirname, './examples/components/c1.js'), 31 | }); 32 | }); 33 | 34 | it('should return `true` when the file is mapped through a glob root config', () => { 35 | expect(resolverPlugin.resolve('c2', path.resolve('./test/examples/components/c1.js'), opts)) 36 | .toEqual({ 37 | found: true, 38 | path: path.resolve(__dirname, './examples/components/sub/sub/c2.js'), 39 | }); 40 | }); 41 | 42 | it('should return `true` when the file uses a custom extension from the babel plugin', () => { 43 | expect(resolverPlugin.resolve('components/customFile', path.resolve('./test/examples/components/c1.js'), opts)) 44 | .toEqual({ 45 | found: true, 46 | path: path.resolve(__dirname, './examples/components/customFile.customExt'), 47 | }); 48 | }); 49 | 50 | it('should return `true` when no mapping is required', () => { 51 | expect(resolverPlugin.resolve('./sub/sub/c2', path.resolve('./test/examples/components/c1'), opts)) 52 | .toEqual({ 53 | found: true, 54 | path: path.resolve(__dirname, './examples/components/sub/sub/c2.js'), 55 | }); 56 | }); 57 | 58 | it('should return `false` when a module is not found', () => { 59 | expect(resolverPlugin.resolve('this_unknown_plugin', path.resolve('./test/example/file1'), opts)) 60 | .toEqual({ found: false }); 61 | }); 62 | 63 | it('should return `false` when the mapped file is not found', () => { 64 | expect(resolverPlugin.resolve('components/noc1', path.resolve('./test/examples/components/subcomponent/sub/c2'), opts)) 65 | .toEqual({ found: false }); 66 | }); 67 | 68 | it('should return `path: null` for core modules', () => { 69 | expect(resolverPlugin.resolve('fs', path.resolve('./'), opts)) 70 | .toEqual({ found: true, path: null }); 71 | expect(resolverPlugin.resolve('path', path.resolve('./'), opts)) 72 | .toEqual({ found: true, path: null }); 73 | }); 74 | 75 | describe('with webpack paths', () => { 76 | it('should support a path with a query', () => { 77 | expect(resolverPlugin.resolve('components/c1?q=sth', path.resolve('./test/examples/components/sub/sub/c2.js'), opts)) 78 | .toEqual({ 79 | found: true, 80 | path: path.resolve(__dirname, './examples/components/c1.js'), 81 | }); 82 | }); 83 | 84 | it('should support a path with a loader', () => { 85 | expect(resolverPlugin.resolve('my-loader!components/c1', path.resolve('./test/examples/components/sub/sub/c2.js'), opts)) 86 | .toEqual({ 87 | found: true, 88 | path: path.resolve(__dirname, './examples/components/c1.js'), 89 | }); 90 | }); 91 | 92 | it('should support multiple loaders', () => { 93 | expect(resolverPlugin.resolve('style-loader!css-loader!less-loader!components/c1', path.resolve('./test/examples/components/sub/sub/c2.js'), opts)) 94 | .toEqual({ 95 | found: true, 96 | path: path.resolve(__dirname, './examples/components/c1.js'), 97 | }); 98 | }); 99 | 100 | it('should support multiple loaders for an alias with an exclamation mark', () => { 101 | expect(resolverPlugin.resolve('style-loader!css-loader!less-loader!!src/c1', path.resolve('./test/examples/components/sub/sub/c2.js'), opts)) 102 | .toEqual({ 103 | found: true, 104 | path: path.resolve(__dirname, './examples/components/c1.js'), 105 | }); 106 | }); 107 | }); 108 | 109 | describe('with specific file extensions', () => { 110 | it('should return `false` with a file with an unknown extension', () => { 111 | expect(resolverPlugin.resolve('./c3', path.resolve('./test/examples/components/c1'), opts)) 112 | .toEqual({ found: false }); 113 | }); 114 | 115 | it('should return `true` with a file with an expected extension', () => { 116 | expect(resolverPlugin.resolve('./c3', path.resolve('./test/examples/components/c1'), extensionOpts)) 117 | .toEqual({ 118 | found: true, 119 | path: path.resolve(__dirname, './examples/components/c3.jsx'), 120 | }); 121 | }); 122 | 123 | it('should return `false` when mapped to a file with an unknown extension', () => { 124 | expect(resolverPlugin.resolve('components/c3', path.resolve('./test/examples/components/subcomponent/sub/c2'), opts)) 125 | .toEqual({ found: false }); 126 | }); 127 | 128 | it('should return `true` when mapped to a file with an expected extension', () => { 129 | expect(resolverPlugin.resolve('components/c3', path.resolve('./test/examples/components/subcomponent/sub/c2'), extensionOpts)) 130 | .toEqual({ 131 | found: true, 132 | path: path.resolve(__dirname, './examples/components/c3.jsx'), 133 | }); 134 | }); 135 | 136 | it('should return `true` when alias contains an exclamation mark', () => { 137 | expect(resolverPlugin.resolve('!src/c3', path.resolve('./test/examples/components/subcomponent/sub/c2'), extensionOpts)) 138 | .toEqual({ 139 | found: true, 140 | path: path.resolve(__dirname, './examples/components/c3.jsx'), 141 | }); 142 | }); 143 | }); 144 | 145 | describe('mapping only in specific environment', () => { 146 | describe('when both the default and "env" are available', () => { 147 | it('should return `false` when the mapping doesn\'t exist in "env"', () => { 148 | const oldEnv = process.env.NODE_ENV; 149 | process.env.NODE_ENV = 'development'; 150 | 151 | expect(resolverPlugin.resolve('subsub/c2', path.resolve('./test/examples/components/c1'), opts)) 152 | .toEqual({ found: false }); 153 | 154 | process.env.NODE_ENV = oldEnv; 155 | }); 156 | 157 | it('should return `true` when the mapping exists in the "env"', () => { 158 | const oldEnv = process.env.NODE_ENV; 159 | process.env.NODE_ENV = 'testenv'; 160 | 161 | expect(resolverPlugin.resolve('subsub/c2', path.resolve('./test/examples/components/c1'), opts)) 162 | .toEqual({ 163 | found: true, 164 | path: path.resolve(__dirname, './examples/components/sub/sub/c2.js'), 165 | }); 166 | 167 | process.env.NODE_ENV = oldEnv; 168 | }); 169 | }); 170 | 171 | describe('when a specific env is available', () => { 172 | it('should return `false` when the mapping doesn\'t exist in "env"', () => { 173 | const oldEnv = process.env.NODE_ENV; 174 | process.env.NODE_ENV = 'development'; 175 | 176 | expect(resolverPlugin.resolve('subsub/c2', path.resolve('./test/examples/components/sub/envonly/yo'), opts)) 177 | .toEqual({ found: false }); 178 | 179 | process.env.NODE_ENV = oldEnv; 180 | }); 181 | 182 | it('should return `true` when the mapping exists in the "env"', () => { 183 | const oldEnv = process.env.NODE_ENV; 184 | process.env.NODE_ENV = 'testenv'; 185 | 186 | expect(resolverPlugin.resolve('subsub/c2', path.resolve('./test/examples/components/sub/envonly/yo'), opts)) 187 | .toEqual({ 188 | found: true, 189 | path: path.resolve(__dirname, './examples/components/sub/sub/c2.js'), 190 | }); 191 | 192 | process.env.NODE_ENV = oldEnv; 193 | }); 194 | }); 195 | }); 196 | 197 | describe('usage in a monorepo', () => { 198 | it('should return `true` when mapped to a file', () => { 199 | expect(resolverPlugin.resolve('~/item', path.resolve('./test/examples/monorepo/my-lib/src/item'), extensionOpts)) 200 | .toEqual({ 201 | found: true, 202 | path: path.resolve(__dirname, './examples/monorepo/my-lib/src/item.js'), 203 | }); 204 | }); 205 | }); 206 | 207 | describe('allowExistingDirectories', () => { 208 | it('should return `true` when directory exists', () => { 209 | expect(resolverPlugin.resolve('components/sub', path.resolve('./test/examples/components/sub/c1'), { ...opts, allowExistingDirectories: true })) 210 | .toEqual({ 211 | found: true, 212 | path: `${path.resolve(__dirname, './examples/components/sub')}/`, 213 | }); 214 | }); 215 | }); 216 | }); 217 | --------------------------------------------------------------------------------