UNPKG

@addon24/eslint-config

Version:

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

113 lines (98 loc) 3.55 kB
/** * @fileoverview Erzwingt die Verwendung von DTO-Klassen anstelle von Interfaces */ "use strict"; const preferDtoClassesRule = { meta: { type: "suggestion", docs: { description: "Erzwingt die Verwendung von DTO-Klassen anstelle von Interfaces für Datenübertragung", category: "Best Practices", recommended: true, }, fixable: null, schema: [], messages: { preferDtoClass: "Interface '{{interfaceName}}' sollte als DTO-Klasse implementiert werden. DTO-Klassen bieten Runtime-Validierung, bessere Type Safety und Konsistenz.", useFactoryFunction: "Wenn ein Interface für '{{interfaceName}}' notwendig ist (z.B. interne Types), füge eine Factory-Funktion hinzu: 'export const create{{interfaceName}} = (...) => ({ ... });'", }, }, create(context) { const filename = context.getFilename(); // Nur DTO-Dateien prüfen if (!filename.includes("/dto/") || filename.includes("test") || filename.includes("spec")) { return {}; } // Identifiziere DTO-Interfaces function isDtoInterface(interfaceName) { return ( interfaceName.endsWith("Dto") || interfaceName.endsWith("DTO") || interfaceName.includes("Request") || interfaceName.includes("Response") || interfaceName.includes("Create") || interfaceName.includes("Update") || interfaceName.includes("Delete") || interfaceName.includes("Model") || interfaceName.includes("Data") ); } // Ausnahmen für akzeptable Interface-Verwendungen function isAcceptableInterface(interfaceName, context) { const internalTypePatterns = [ "Type", "Config", "Options", "Settings", "Props", "State" ]; const componentPatterns = [ "Component", "Hook", "Context" ]; return ( internalTypePatterns.some(pattern => interfaceName.includes(pattern)) || componentPatterns.some(pattern => interfaceName.includes(pattern)) || filename.includes("/types/") || // Reine Type-Definitionen filename.includes("/model/") // Business Models ); } return { TSInterfaceDeclaration(node) { const interfaceName = node.id.name; if (isDtoInterface(interfaceName) && !isAcceptableInterface(interfaceName, context)) { // Prüfe, ob eine Factory-Funktion existiert const sourceCode = context.getSourceCode(); const text = sourceCode.getText(); const hasFactoryFunction = text.includes(`create${interfaceName}`) || text.includes(`new${interfaceName}`); if (!hasFactoryFunction) { context.report({ node, messageId: "preferDtoClass", data: { interfaceName } }); } else { // Warnung mit Hinweis auf Factory-Pattern context.report({ node, messageId: "useFactoryFunction", data: { interfaceName } }); } } }, // Prüfe auch Type-Aliase TSTypeAliasDeclaration(node) { const typeName = node.id.name; if (isDtoInterface(typeName) && !isAcceptableInterface(typeName, context)) { context.report({ node, messageId: "preferDtoClass", data: { interfaceName: typeName } }); } } }; } }; export default { rules: { "prefer-dto-classes": preferDtoClassesRule, }, };