ESLint Rule Composer is a utility library designed to facilitate the creation and modification of ESLint rules by composing them from existing ones. Currently at version 0.3.0, it allows developers to `filterReports`, `mapReports`, or `joinReports` from one or more base rules, enabling highly customized linting behavior without needing to rewrite entire rule definitions. This approach is particularly useful for adding exceptions to existing rules (e.g., ignoring specific patterns in `no-unused-expressions`) or combining the logic of multiple rules. Its primary differentiator is the programmatic manipulation of reported problems and rule definitions, offering a flexible layer over ESLint's core rule API. Given its 0.x.y version, API stability might still be evolving, and its release cadence is likely slow or on-demand, as the last update on NPM was in April 2018.
npm install eslint-rule-composerVerified import paths — ran on the pinned version, not inferred.
This example demonstrates how to create a custom ESLint rule using `eslint-rule-composer` to modify the behavior of an existing core rule, specifically `no-unused-expressions`, to ignore specific patterns. It also shows the necessary setup for integrating the composed rule into an ESLint configuration.
Pin the exact version (e.g., `"eslint-rule-composer": "0.3.0"`) in `package.json` to prevent unexpected breaking changes on update, or implement robust integration tests for your custom rules.
Test your custom rules against the specific `eslint` version(s) used in your project. Refer to ESLint's release notes for any breaking changes in its public API or internal structures.
Always implement defensive checks when accessing rule options. For example, `const whitelist = metadata.options?.[0]?.whitelist || [];` to safely access properties and provide fallbacks.
For CommonJS-based projects or older `.eslintrc.js` configurations, `require()` works as shown. For modern ESLint flat configs (`eslint.config.js`) or ESM projects, you might need to wrap `require()` or use a transpilation step if direct `import` is not supported.
Ensure `const ruleComposer = require('eslint-rule-composer');` is used and the package is correctly installed. Double-check the path if it's a local file.Verify that `const { Linter } = require('eslint');` is correctly used and `const linter = new Linter();` is called before accessing `linter.getRules()`.Add defensive coding for accessing rule options: `const whitelist = metadata.options?.[0]?.whitelist || [];` to safely handle cases where options might not be provided in the ESLint configuration.