@addon24/eslint-config
Version:
ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types
177 lines (150 loc) • 6.13 kB
JavaScript
export default {
rules: {
"enforce-dto-naming": {
meta: {
type: "problem",
docs: {
description: "Enforce correct DTO naming conventions and filename matching",
category: "Best Practices",
recommended: true,
},
fixable: null,
schema: [],
messages: {
invalidDtoSuffix: "Invalid DTO suffix pattern. Avoid double suffixes like 'DtoEntityDto', 'EntityDtoEntityDto', or 'EntityEntityDto'. Use only one suffix: 'EntityDto' for entity DTOs or 'Dto' for other DTOs.",
filenameMismatch: "Filename '{{filename}}' does not match class name '{{className}}'. Rename the file to '{{expectedFilename}}'.",
suggestCorrectName: "Consider renaming the class to '{{suggestedName}}' to match the filename.",
suggestCorrectFilename: "Consider renaming the file to '{{suggestedFilename}}' to match the class name.",
},
},
create(context) {
function hasInvalidDtoSuffix(className) {
// Verbotene Muster:
// - DtoEntityDto (doppeltes Dto)
// - EntityDtoEntityDto (doppeltes EntityDto)
// - EntityEntityDto (doppeltes Entity)
// - DtoDto (doppeltes Dto)
const invalidPatterns = [
/DtoEntityDto$/, // DtoEntityDto
/EntityDtoEntityDto$/, // EntityDtoEntityDto
/EntityEntityDto$/, // EntityEntityDto
/DtoDto$/, // DtoDto
/EntityEntity$/, // EntityEntity
/DtoEntityEntity$/, // DtoEntityEntity
/EntityDtoEntity$/, // EntityDtoEntity
];
return invalidPatterns.some(pattern => pattern.test(className));
}
function getValidDtoSuffix(className) {
// Entferne alle bekannten Suffixe
let cleanName = className
.replace(/EntityDto$/, '')
.replace(/Dto$/, '')
.replace(/Entity$/, '');
// Füge den korrekten Suffix hinzu
if (className.endsWith('EntityDto')) {
return `${cleanName}EntityDto`;
} else if (className.endsWith('Dto')) {
return `${cleanName}Dto`;
} else if (className.endsWith('Entity')) {
return `${cleanName}Entity`;
}
// Standardfall: Dto hinzufügen
return `${cleanName}Dto`;
}
function getExpectedFilename(className) {
return `${className}.ts`;
}
function getCurrentFilename(context) {
const filename = context.getFilename();
// Extrahiere den Dateinamen ohne Pfad und Erweiterung
const pathParts = filename.split('/');
const filenameWithExt = pathParts[pathParts.length - 1];
return filenameWithExt.replace(/\.ts$/, '');
}
function isDtoFile(filename) {
// Prüfe, ob es sich um eine DTO-Datei handelt
return filename.includes('Dto') || filename.includes('Entity');
}
function isTestFile(filename) {
return filename.includes('.test.') ||
filename.includes('.spec.') ||
filename.includes('__tests__');
}
return {
ClassDeclaration(node) {
if (!node.id) return;
const className = node.id.name;
const currentFilename = getCurrentFilename(context);
// Überspringe Test-Dateien
if (isTestFile(currentFilename)) return;
// Prüfe nur DTO-Dateien
if (!isDtoFile(currentFilename)) return;
// Regel 1: Prüfe auf ungültige DTO-Suffixe
if (hasInvalidDtoSuffix(className)) {
const validName = getValidDtoSuffix(className);
context.report({
node: node.id,
messageId: "invalidDtoSuffix",
data: {
className,
suggestedName: validName,
},
});
}
// Regel 2: Prüfe auf Dateiname-Klassenname-Übereinstimmung
if (currentFilename !== className) {
const expectedFilename = getExpectedFilename(className);
context.report({
node: node.id,
messageId: "filenameMismatch",
data: {
filename: currentFilename,
className,
expectedFilename,
suggestedFilename: expectedFilename,
},
});
}
},
ExportDefaultDeclaration(node) {
if (node.declaration.type !== 'ClassDeclaration') return;
if (!node.declaration.id) return;
const className = node.declaration.id.name;
const currentFilename = getCurrentFilename(context);
// Überspringe Test-Dateien
if (isTestFile(currentFilename)) return;
// Prüfe nur DTO-Dateien
if (!isDtoFile(currentFilename)) return;
// Regel 1: Prüfe auf ungültige DTO-Suffixe
if (hasInvalidDtoSuffix(className)) {
const validName = getValidDtoSuffix(className);
context.report({
node: node.declaration.id,
messageId: "invalidDtoSuffix",
data: {
className,
suggestedName: validName,
},
});
}
// Regel 2: Prüfe auf Dateiname-Klassenname-Übereinstimmung
if (currentFilename !== className) {
const expectedFilename = getExpectedFilename(className);
context.report({
node: node.declaration.id,
messageId: "filenameMismatch",
data: {
filename: currentFilename,
className,
expectedFilename,
suggestedFilename: expectedFilename,
},
});
}
},
};
},
},
},
};