Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disallow barrel file imports within the same library in Nrwl Nx

Suppose we have an app and a library in Nrwl Nx.

/apps
  /myApp

/libs
  /myLib
    /components
       /my.component.ts
       /other.component.ts
    /index.ts

I have already set tags in nx.json and nx-enforce-module-boundaries rule to block importing the app inside the lib. It works and this part is fine.

Another thing I wanted to do is enforcing using barrel files within libraries. So I created a path in tsconfig.ts

"paths": {
   "@myNs/my-lib": ["libs/myLib/index.ts"]
}

I faced the problem. Suppose we have something exported from index.ts.

// index.ts
export { MyComponent } from './components/my.component';

Now if we use some autoimporting IDE feature (e.g. from WebStorm or VS Code). They will be importing MyComponent using the path @myNs/my-lib - and this is expected, because I have just configured it like so.

A real problem appears when I want to autoimport something inside myLib (these imports should be relative, not @myNs/my-lib) - according to logic and this article ([Interesting article here]):

Never let a lib import from its own Barrel file

The TypeScript modules within a particular lib should not care what functionality that lib exposes, so it shouldn’t use its own barrel file at any point.

If a module imports something from its own barrel file, it almost always results in circular reference errors. Therefore, imports from inside of the module should use relative path imports.

So I found a workaround to block TS path-like imports inside lib. I have added a rule inside libs/myLib/tslint.json:

"rules": {
   "import-blacklist": [true, "@myNs/my-lib"]
}

Anyway, it doesn't fix autoimporting feature, just disallows to use wrong imports inside the lib.

Another problem is there are still wrong imports allowed. Suppose OtherComponent wants to import MyComponent Then there are three possibilities:

import { MyComponent } from './my.component'; // the correct way
import { MyComponent } from '.'; // not the best, but also the correct way
import { MyComponent } from '..'; // using barrel file - not correct (look at the citation above), but still successfuly validated by TSLint

Questions:

  1. How to disallow barrel file imports inside the same lib?
  2. How to configure IDEs to have relative paths inside lib and TypeScript paths outside (@myNs/my-lib)?
like image 320
Nickon Avatar asked Jan 25 '23 08:01

Nickon


2 Answers

Here's the setting in IntelliJ. I am seeing this work correctly in v2020.1.

setting in IntelliJ under Editor > Code Style > Typescript named "Use path mappings from tsconfig.json set to "Only in files outside specified paths"

I like the rule @Nickson created however, and think it's a good idea to add to prevent errors!

like image 86
David Shortman Avatar answered Jan 28 '23 10:01

David Shortman


No one answered, so I decided to create a simple TSLint rule to handle this case: import-blacklist-extended

Rule works fine in Nrwl monorepo, but it could be optimized and some mechanisms could be resolved better. Feel free to create issues and PRs on Github if any changes are needed for you.

like image 42
Nickon Avatar answered Jan 28 '23 10:01

Nickon