Repository: import-js/eslint-plugin-import (JavaScript)

Issue:
How to treat imports inside a monorepo as internal
I am working on a monorepo where I have some files with a list of imports that looks like this:

```
import React from 'react';

import MyComponent from '@my/src/MyComponent';

import styles from './styles.scss';
```

In this example, the second import refers to a package inside the monorepo and I would like it to be treated as an internal import by `import/order`. Is this possible to achieve?


Discussion:
Since technically it’s not internal - that syntax is for npm-installed scoped modules - i don’t believe it’s currently possible.
Would it be possible to add an option to `import/order` that allows you to pass a regex to identify internal imports? In that way I could simply specify that all internal imports start with `@my`.
Is it not an option to use a prefix that isn't also a valid npm package name?
I don't think that is possible in a monorepo. The packages inside a monorepo will always have valid package names since you have to create a package.json for each one of them. Besides that, I need  my packages in the monorepo to be scoped. This is also how other projects like babel and jest are doing it.

Another option would also be to check via the root package.json if the current project is a monorepo, to determine where the modules are located and consider those internal (I mean by reading the [workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) property). Or is this the wrong way around?
I think it should simply be possible for us to specify what's treated as "internal". 
See also my comment in https://github.com/benmosher/eslint-plugin-import/issues/807#issuecomment-415358830, which actually belongs here rather than in the other issue.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81ca852140..d075a16e3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 
 ## [Unreleased]
 
+### Added
+- [`internal-regex`]: regex pattern for marking packages "internal"  ([#1491], thanks [@Librazy])
+
 ### Added
 - [`group-exports`]: make aggregate module exports valid ([#1472], thanks [@atikenny])
 - [`no-namespace`]: Make rule fixable ([#1401], thanks [@TrevorBurnham])
diff --git a/README.md b/README.md
index 76d50f44cf..814d5fc28d 100644
--- a/README.md
+++ b/README.md
@@ -402,6 +402,20 @@ settings:
 [`eslint_d`]: https://www.npmjs.com/package/eslint_d
 [`eslint-loader`]: https://www.npmjs.com/package/eslint-loader
 
+#### `import/internal-regex`
+
+A regex for packages should be treated as internal. Useful when you are utilizing a monorepo setup or developing a set of packages that depend on each other.
+
+By default, any package referenced from [`import/external-module-folders`](#importexternal-module-folders) will be considered as "external", including packages in a monorepo like yarn workspace or lerna emvironentment. If you want to mark these packages as "internal" this will be useful.
+
+For example, if you pacakges in a monorepo are all in `@scope`, you can configure `import/internal-regex` like this
+
+```yaml
+# .eslintrc.yml
+settings:
+  import/internal-regex: ^@scope/
+```
+
 
 ## SublimeLinter-eslint
 
diff --git a/docs/rules/order.md b/docs/rules/order.md
index 88ddca46fb..d716430481 100644
--- a/docs/rules/order.md
+++ b/docs/rules/order.md
@@ -168,4 +168,8 @@ import sibling from './foo';
 
 - [`import/external-module-folders`] setting
 
+- [`import/internal-regex`] setting
+
 [`import/external-module-folders`]: ../../README.md#importexternal-module-folders
+
+[`import/internal-regex`]: ../../README.md#importinternal-regex
diff --git a/src/core/importType.js b/src/core/importType.js
index b948ea2bb9..a3480ae12a 100644
--- a/src/core/importType.js
+++ b/src/core/importType.js
@@ -54,8 +54,9 @@ export function isScopedMain(name) {
 }
 
 function isInternalModule(name, settings, path) {
+  const internalScope = (settings && settings['import/internal-regex'])
   const matchesScopedOrExternalRegExp = scopedRegExp.test(name) || externalModuleRegExp.test(name)
-  return (matchesScopedOrExternalRegExp && !isExternalPath(path, name, settings))
+  return (matchesScopedOrExternalRegExp && (internalScope && new RegExp(internalScope).test(name) || !isExternalPath(path, name, settings)))
 }
 
 function isRelativeToParent(name) {


Test patch:
diff --git a/tests/src/core/importType.js b/tests/src/core/importType.js
index 07466bfa92..c85124a1f4 100644
--- a/tests/src/core/importType.js
+++ b/tests/src/core/importType.js
@@ -51,7 +51,7 @@ describe('importType(name)', function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@importType/index', pathContext)).to.equal('internal')
   })
-    
+
   it("should return 'internal' for internal modules that are referenced by aliases", function () {
     const pathContext = testContext({ 'import/resolver': { node: { paths: [pathToTestFiles] } } })
     expect(importType('@my-alias/fn', pathContext)).to.equal('internal')
@@ -130,6 +130,16 @@ describe('importType(name)', function () {
     expect(importType('resolve', foldersContext)).to.equal('internal')
   })
 
+  it("should return 'internal' for module from 'node_modules' if its name matched 'internal-regex'", function() {
+    const foldersContext = testContext({ 'import/internal-regex': '^@org' })
+    expect(importType('@org/foobar', foldersContext)).to.equal('internal')
+  })
+
+  it("should return 'external' for module from 'node_modules' if its name did not match 'internal-regex'", function() {
+    const foldersContext = testContext({ 'import/internal-regex': '^@bar' })
+    expect(importType('@org/foobar', foldersContext)).to.equal('external')
+  })
+
   it("should return 'external' for module from 'node_modules' if 'node_modules' contained in 'external-module-folders'", function() {
     const foldersContext = testContext({ 'import/external-module-folders': ['node_modules'] })
     expect(importType('resolve', foldersContext)).to.equal('external')