javierbrea / eslint-plugin-boundaries

Eslint plugin checking architecture boundaries between elements
MIT License
474 stars 8 forks source link

Configuring boundaries/entry-point depending on "from" #212

Closed jesperume closed 2 years ago

jesperume commented 2 years ago

Thanks for a great library!

I'm trying to configure boundaries/entry-point but I'm not sure how do it.

I have this folder structure

src/
├── components/
├── pages/
├── utils/

I want to configure so that each of the elements only can can be accessible through the index.js file. pages/page-1.js can only imports component via components/index.ts components/button/button.js can only imports utils via utils/index.ts

So this configuration works:

"boundaries/entry-point": [
      2,
      {
       default: "disallow",
        rules: [
          {
            target: ["components", "utils"],
            allow: "index.js",
          },
        ],
      },
    ],

However, when the scope is within each of the elements (components, utils) it should be possible to import the files directly. components/menu/menu.js can import components/button/button.js directly and not be forced to do it via (components/index.js) utils/util-1.js can import utils/util-2.js directly and not be forced to do it via (utils/index.js)

How do I configure that?

javierbrea commented 2 years ago

Hi @jesperume, the entry-point rule can be used only to ensure that each element is imported through a file belonging to the element itself. If I have understood well, you are trying to set a common index.js file that should be the entry point for all of the elements of a type. In that case, maybe you could define new element types for the index files, and allow other elements to import only them using the element-types rule. Something like this:

{
    // disallow all local imports by default
    default: "disallow",
    rules: [
      {
        from: ["components-index"],
        allow: ["components"],
      },
      {
        from: ["components"],
        allow: ["components-index", "utils-index"],
      },
      {
        from: ["utils-index"],
        allow: ["utils"],
      },
      {
        from: ["utils"],
        allow: ["utils-index"],
      },
    ],
  },

But note that this configuration may result in circular dependencies, because you are importing all components from the components/index.js file, and forcing components to import other components also using that file.

About components being able to import other components "ignoring" the entry-point rule, make sure that all of your element file types are being detected properly by the plugin. You may review your boundaries/elements settings, and use the ESLINT_PLUGIN_BOUNDARIES_DEBUG environment variable to check that every file type is being assigned as expected. If you need more help on this, please provide a full example of your configuration and files structure (a public repository containing it would be great, so anyone could review the configuration easily or even open a PR fixing it)

jesperume commented 2 years ago

Thank you @javierbrea. This should be what I'm looking for. You are right about the circular dependencies. I ran this utility https://github.com/pahen/madge and it seems that I already have som circular dependencies that I need to take care of first. I might need to tweak the boundaries/element-types config. But It's a good start, thanks!