UNPKG

@addon24/eslint-config

Version:

ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types

213 lines (200 loc) 8.67 kB
import path from "path"; export default { meta: { type: "problem", docs: { description: "Enforces DTO naming and folder conventions", category: "Architecture", recommended: true, }, schema: [], messages: { classNameMismatch: "Klassenname '{{className}}' muss mit dem Dateinamen '{{filename}}' übereinstimmen.", entityDtoWrongSuffix: "Entity-DTO '{{className}}' muss den Suffix 'EntityDto' haben (nicht '{{currentSuffix}}')", entityDtoDoubleSuffix: "Entity-DTO '{{className}}' hat doppelten Suffix. Verwende '{{correctName}}' statt '{{className}}'", entityDtoMixedType: "Entity-DTO '{{className}}' darf keine anderen DTO-Typen im Namen haben (z.B. 'Response', 'Request'). Verwende '{{correctName}}' statt '{{className}}'", responseDtoWrongSuffix: "Response-DTO '{{className}}' muss den Suffix 'ResponseDto' haben (nicht '{{currentSuffix}}')", requestDtoWrongSuffix: "Request-DTO '{{className}}' muss den Suffix 'RequestDto' haben (nicht '{{currentSuffix}}')", configDtoWrongSuffix: "Config-DTO '{{className}}' muss den Suffix 'ConfigDto' haben (nicht '{{currentSuffix}}')", filterDtoWrongSuffix: "Filter-DTO '{{className}}' muss den Suffix 'FilterDto' haben (nicht '{{currentSuffix}}')", unknownFolderSuffix: "DTO '{{className}}' im unbekannten Ordner '{{folder}}'. Definiere einen passenden Suffix.", dtoMustBeInSubfolder: "DTO '{{className}}' muss in einem Unterordner von /dto/ liegen (z.B. /dto/Response/, /dto/Request/, etc.).", }, }, create(context) { return { ClassDeclaration(node) { const filename = context.getFilename(); const dtoClassName = node.id?.name; if (!dtoClassName) return; const baseFilename = path.basename(filename, ".ts"); // 1. Klassenname und Dateiname müssen übereinstimmen if (dtoClassName !== baseFilename) { context.report({ node: node, messageId: "classNameMismatch", data: { className: dtoClassName, filename: baseFilename }, }); } // 2. Bestimme den Ordner und erwarteten Suffix const pathParts = filename.split(path.sep); const dtoIndex = pathParts.findIndex(part => part === "dto"); if (dtoIndex !== -1) { // Ausnahme für BaseEntityDto (abstrakte Base-Klasse) if (dtoClassName === "BaseEntityDto" && filename.endsWith("/dto/BaseEntityDto.ts")) { return; } // Prüfe, ob es ein Unterordner gibt (nicht die Datei selbst) if (dtoIndex + 1 < pathParts.length - 1) { const folder = pathParts[dtoIndex + 1]; const currentSuffix = dtoClassName.match(/([A-Z][a-z]*Dto)$/)?.[1] || "unbekannt"; const expectedSuffixMap = { "Entity": "EntityDto", "Response": "ResponseDto", "Request": "RequestDto", "Config": "ConfigDto", "Filter": "FilterDto", // Add other common DTO subfolders here if they have a specific suffix // For example, if you have /dto/Auth/AuthRequestDto, you'd add "Auth": "AuthDto" // For now, general DTOs in other folders just need to end with "Dto" "Wot": "Dto", "Game": "Dto", "User": "Dto", "Auth": "Dto", "Chat": "Dto", "World": "Dto", "Asset": "Dto", "Language": "Dto", "Log": "Dto", "Health": "Dto", "Metrics": "Dto", "Admin": "Dto", "Utilities": "Dto", "Common": "Dto", "Shared": "Dto", "Core": "Dto", "System": "Dto", "Event": "Dto", "Notification": "Dto", "Payment": "Dto", "Inventory": "Dto", "Quest": "Dto", "Skill": "Dto", "Spell": "Dto", "Item": "Dto", "Faction": "Dto", "Race": "Dto", "Class": "Dto", "Ability": "Dto", "Buff": "Dto", "Debuff": "Dto", "Effect": "Dto", "Stat": "Dto", "Map": "Dto", "Zone": "Dto", "Region": "Dto", "Server": "Dto", "Client": "Dto", "Gateway": "Dto", "Proxy": "Dto", "Service": "Dto", "Module": "Dto", "Provider": "Dto", "Repository": "Dto", "Controller": "Dto", "Middleware": "Dto", "Guard": "Dto", "Interceptor": "Dto", "Pipe": "Dto", "Decorator": "Dto", "Enum": "Dto", "Interface": "Dto", "Type": "Dto", "Util": "Dto", "Helper": "Dto", "Constant": "Dto", "Factory": "Dto", "Strategy": "Dto", "Subscriber": "Dto", "Seeder": "Dto", "Migration": "Dto", "Test": "Dto", "Mock": "Dto", "Stub": "Dto", "Fixture": "Dto", "Seed": "Dto", "Script": "Dto", "Tool": "Dto", "Logger": "Dto", // Added Logger as a recognized folder, but no specific suffix beyond Dto "Main": "Dto", // Added Main as a recognized folder, but no specific suffix beyond Dto "OAuth": "Dto", // Added OAuth as a recognized folder, but no specific suffix beyond Dto "Utility": "Dto", // Added Utility as a recognized folder, but no specific suffix beyond Dto }; const expectedSuffix = expectedSuffixMap[folder]; if (folder === "Entity") { if (!dtoClassName.endsWith("EntityDto")) { context.report({ node: node, messageId: "entityDtoWrongSuffix", data: { className: dtoClassName, currentSuffix: currentSuffix }, }); } else if (dtoClassName.endsWith("DtoEntityDto")) { const correctName = dtoClassName.replace("DtoEntityDto", "EntityDto"); context.report({ node: node, messageId: "entityDtoDoubleSuffix", data: { className: dtoClassName, correctName: correctName }, }); } else { // Prüfe, ob Entity-DTO andere DTO-Typen im Namen hat const forbiddenTypes = ["Response", "Request", "Config", "Filter"]; const hasForbiddenType = forbiddenTypes.some(type => dtoClassName.includes(type) ); if (hasForbiddenType) { // Entferne den verbotenen Typ und ersetze durch korrekten Namen let correctName = dtoClassName; forbiddenTypes.forEach(type => { if (correctName.includes(type)) { correctName = correctName.replace(type, ""); } }); // Stelle sicher, dass es mit EntityDto endet if (!correctName.endsWith("EntityDto")) { correctName = correctName.replace(/Dto$/, "EntityDto"); } context.report({ node: node, messageId: "entityDtoMixedType", data: { className: dtoClassName, correctName: correctName }, }); } } } else if (expectedSuffix && expectedSuffix !== "Dto") { if (!dtoClassName.endsWith(expectedSuffix)) { context.report({ node: node, messageId: `${folder.toLowerCase()}DtoWrongSuffix`, data: { className: dtoClassName, currentSuffix: currentSuffix }, }); } } else if (!expectedSuffix) { context.report({ node: node, messageId: "unknownFolderSuffix", data: { className: dtoClassName, folder: folder }, }); } } else { // DTO direkt im /dto/ Ordner - nicht erlaubt context.report({ node: node, messageId: "dtoMustBeInSubfolder", data: { className: dtoClassName }, }); } } }, }; }, };