javierbrea / eslint-plugin-boundaries

Eslint plugin checking architecture boundaries between elements
MIT License
473 stars 9 forks source link

Support using functions for defining custom messages #315

Open budarin opened 7 months ago

budarin commented 7 months ago

Is your feature request related to a problem? Please describe.

In different layers, depending on the imported file, we want to show the exact message, which cannot be expressed in one phrase for all cases, as it is implemented now in the form of a template

Describe the solution you'd like

For example, by default, all imports are disallowed For the UI layer, for hooks (starting with use*), it is allowed to import from use_cases At the same time, in the other UI modules, import is not allowed and in them we receive a uniform message that says nothing: There is no rule..." although knowing that the file is imported from use_cases into the module is not a hook in the UI layer, I could write "Use_cases are allowed to be imported only into hooks"

javierbrea commented 7 months ago

Interface suggestion

Hello, this could be done, as you suggested, by supporting the usage of functions in the message property of the configuration. It should receive an object with the information about the current file and the dependency being imported. For example:

{
  rules: {
    "boundaries/element-types": [2, {
      default: "allow",
      message: ({ file, dependency }) => {
          return "${file.type} is not allowed to import ${dependency.type}";
      },
      rules: [
        {
          from: ["helpers"],
          disallow: ["modules", "components"],
          importKind: "value",
          message: ({ file, dependency }) => {
             return "${file.type} is not allowed to import ${dependency.type}";
          },
        },
      ]
    }]
  }
}

This should be supported both in the general message property and in the message property of each specific rule. Properties to be passed should be the same than are passed currently to the templates. And aliases "from" and "target" should be also provided to keep consistency with the templating format for the definition of the rules, because it is pending to be normalized some day.

Workaround

Until this is implemented, there is a possible workaround that you could use for receiving different messages @budarin. You could set a "disallow" rule with a negative pattern and a custom message, which would be more specific that the general "disallow", and, therefore, it would be the one returned. For example:

rules: {
  "boundaries/element-types": [
     2,
     {
       default: "disallow",
       message: "Custom general message",
       rules: [
          {
             // note the usage of "!" to define "in everything except hooks"
              from: "!hooks",
              disallow: ["use_cases"],
              message: "Use_cases are allowed to be imported only into hooks",
           },
           {
              from: "hooks",
              allow: ["use_cases"],
           }
       ]
     }
  ]
}
budarin commented 7 months ago

the same functionality is required for boundaries/entry-point and other configurations, which throws errors