Given the specificity of your situation, it seems like creating a custom solution may be necessary. Thankfully, eslint offers options for developing custom rules.
In this scenario, where the number of exported members exceeds 1, targeting instances where the export is an object can be achieved. The implementation could resemble the following:
const MAX_NUM_EXPORTS = 2;
module.exports = {
meta: {
messages: {
maxExports: `Modules can only contain up to ${MAX_NUM_EXPORTS} exports`
}
},
create(context) {
return {
ExportDefaultDeclaration(node) {
if (
node.declaration.type === "ObjectExpression"
&& node.declaration.properties.length > MAX_NUM_EXPORTS
) {
context.report({ node, messageId: 'maxExports'})
}
},
ExportNamedDeclaration(node) {
if (node.declaration.type === "VariableDeclaration") {
node.declaration.declarations.forEach(dec => {
if (
dec.init.type === "ObjectExpression"
&& dec.init.properties.length > MAX_NUM_EXPORTS
) {
context.report({ node, messageId: 'maxExports'})
}
})
}
}
}
}
}
The create
method returns callbacks, and utilizing an AST Explorer helps identify which nodes in the tree to target for the rule execution within eslint. Particularly, focusing on the ExportNamedDeclaration
node for standard variable exports and the ExportNamedDeclaration
node for default exports.
After capturing these nodes, the script verifies if they are objects and if those objects exceed the defined limits in terms of properties. If so, an error message is triggered.
Further information on eslint custom rules can be found in the mentioned documentation.
To verify the effectiveness of these rules, leveraging the built-in eslint RuleTester class, paired with preferred testing frameworks, such as the Jest unit testing suite, is recommended.
Implementing the RuleTester
class in a file named rule.test.js
would appear similar to the example below:
const { RuleTester } = require('eslint');
const limitMaxExports = require('./rule');
const ruleTester = new RuleTester(
{
parserOptions: {
ecmaVersion: 6,
sourceType: 'module'
}
}
);
const valid = JSON.stringify({
a: 'this',
b: 'is valid'
});
const invalid = JSON.stringify({
a: 'this',
b: 'has',
c: 'too many'
});
ruleTester.run('limit-max-exports', limitMaxExports, {
valid: [
{
code: `export default ${valid}`
},
{
code: `export const blah = ${valid}`
}
],
invalid: [
{
code: `export default ${invalid}`,
errors: [{messageId: 'maxExports'}]
},
{
code: `export const invalid = ${invalid}`,
errors: [{messageId: 'maxExports'}]
}
]
});
Upon testing with jest, successful completion of all tests will be indicated:
https://i.stack.imgur.com/Virqy.png
Note that this demonstration is tailored for es6
modules exclusively, as specified in the RuleTester
instantiation parameter object.