Files
gridpilot.gg/apps/website/eslint-rules/single-export-per-file.js
2026-01-13 00:16:14 +01:00

84 lines
2.2 KiB
JavaScript

/**
* ESLint rule to enforce single export per file
*
* Each file should export exactly one named export (or default export).
* This ensures clear, focused modules.
*/
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce single export per file',
category: 'Best Practices',
recommended: true,
},
fixable: null,
schema: [],
messages: {
multipleExports: 'File should have exactly one export. Found {{count}} exports: {{exports}}',
noExports: 'File should have at least one export',
},
},
create(context) {
let exportCount = 0;
const exportNames = [];
return {
// Track named exports
ExportNamedDeclaration(node) {
if (node.declaration) {
// Exporting a class, function, const, etc.
if (node.declaration.id) {
exportCount++;
exportNames.push(node.declaration.id.name);
} else if (node.declaration.declarations) {
// Multiple const exports
node.declaration.declarations.forEach(decl => {
if (decl.id && decl.id.name) {
exportCount++;
exportNames.push(decl.id.name);
}
});
}
} else if (node.specifiers) {
// Re-exports
node.specifiers.forEach(spec => {
exportCount++;
exportNames.push(spec.exported.name);
});
}
},
// Track default exports
ExportDefaultDeclaration(node) {
exportCount++;
if (node.declaration && node.declaration.id) {
exportNames.push(`default (${node.declaration.id.name})`);
} else {
exportNames.push('default');
}
},
'Program:exit'() {
if (exportCount === 0) {
context.report({
node: context.getSourceCode().ast,
messageId: 'noExports',
});
} else if (exportCount > 1) {
context.report({
node: context.getSourceCode().ast,
messageId: 'multipleExports',
data: {
count: exportCount,
exports: exportNames.join(', '),
},
});
}
},
};
},
};