UNPKG

@addon24/eslint-config

Version:

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

183 lines (166 loc) 6.82 kB
export default { meta: { type: "problem", docs: { description: "Entity-DTOs müssen fromEntity-Methoden bereitstellen", category: "Architecture", recommended: true, }, schema: [ { type: "object", properties: { entityDtoPath: { type: "string", description: "Path pattern for Entity DTO files", default: "/dto/Entity/" }, requireFromEntityArray: { type: "boolean", description: "Whether fromEntityArray method is required", default: false }, allowCreateMethod: { type: "boolean", description: "Whether create method is allowed in Entity DTOs", default: false }, allowGenericMethods: { type: "boolean", description: "Whether generic-specific methods are allowed in Entity DTOs", default: true } }, additionalProperties: false } ], messages: { missingFromEntityMethod: "Entity-DTO-Klasse '{{dtoName}}' muss eine statische fromEntity-Methode bereitstellen", forbiddenCreateMethod: "Entity-DTO-Klasse '{{dtoName}}' darf keine create-Methode haben. Verwende stattdessen fromEntity-Methoden.", missingGenericFromEntityMethod: "Entity-DTO-Klasse '{{dtoName}}' mit Generics muss spezifische fromEntity-Methoden für jeden Generic-Typ bereitstellen", invalidGenericMethodSignature: "Generic-spezifische Methode '{{methodName}}' hat eine ungültige Signatur. Erwartet: {{expectedSignature}}", }, }, create(context) { const filename = context.getFilename(); const options = context.options[0] || {}; const entityDtoPath = options.entityDtoPath || "/dto/Entity/"; const requireFromEntityArray = options.requireFromEntityArray || false; const allowCreateMethod = options.allowCreateMethod || false; const allowGenericMethods = options.allowGenericMethods !== false; // Prüfe, ob es sich um eine Entity-DTO-Datei handelt const isEntityDtoFile = filename.includes(entityDtoPath) || filename.includes("test-fixtures"); if (!isEntityDtoFile) { return {}; } // Skip test files and fixtures if (filename.includes('test') || filename.includes('__tests__') || filename.includes('.test.')) { return {}; } let classNode = null; let dtoClassName = ""; let hasGenericEntity = false; let genericTypes = []; return { ClassDeclaration(node) { classNode = node; dtoClassName = node.id?.name; }, ExportDefaultDeclaration(node) { if (node.declaration.type === "ClassDeclaration") { classNode = node.declaration; dtoClassName = node.declaration.id?.name; } }, ImportDeclaration(node) { // Prüfe, ob eine Generic-Entity importiert wird if (node.source.value.includes("BackpackRefItemEntity")) { hasGenericEntity = true; // Extrahiere Generic-Typen aus der Entity const specifiers = node.specifiers; specifiers.forEach(spec => { if (spec.type === "ImportDefaultSpecifier" && spec.local.name === "BackpackRefItemEntity") { // BackpackRefItemEntity hat die Generic-Typen: IsBackpack, IsEquipped, IsItem genericTypes = ["IsBackpack", "IsEquipped", "IsItem"]; } }); } }, "Program:exit"(node) { if (!classNode || !dtoClassName) return; // Skip if class has test fixture comment const sourceCode = context.getSourceCode(); const classText = sourceCode.getText(classNode); if (classText.includes('Test-Fixture') || classText.includes('keine Validierung erforderlich')) { return; } const methods = classNode.body.body.filter(member => member.type === "MethodDefinition" && member.static === true ); const hasFromEntityMethod = methods.some(method => method.key?.name === "fromEntity" ); const hasCreateMethod = methods.some(method => method.key?.name === "create" ); // Prüfe auf Generic-spezifische Methoden const hasGenericMethods = methods.some(method => method.key?.name === "createInventorySlot" || method.key?.name === "createBackpackSlot" || method.key?.name === "createEquippedSlot" ); // Request-DTOs sind von der fromEntity-Regel ausgenommen const isRequestDto = filename.includes("/dto/Request/"); // Prüfe, ob es sich um eine Entity-DTO handelt const isEntityDto = dtoClassName.includes("EntityDto") || (filename.includes("test-fixtures") && dtoClassName.includes("EntityDto")); if (!isRequestDto && isEntityDto) { // Standard Entity-DTO Validierung if (!hasFromEntityMethod) { context.report({ node: classNode, messageId: "missingFromEntityMethod", data: { dtoName: dtoClassName } }); } if (hasCreateMethod && !allowCreateMethod) { context.report({ node: classNode, messageId: "forbiddenCreateMethod", data: { dtoName: dtoClassName } }); } // Generic-spezifische Validierung if (hasGenericEntity && allowGenericMethods) { // Prüfe, ob Generic-spezifische Methoden vorhanden sind if (!hasGenericMethods) { context.report({ node: classNode, messageId: "missingGenericFromEntityMethod", data: { dtoName: dtoClassName } }); } // Validiere Generic-Methoden-Signaturen methods.forEach(method => { if (method.key?.name === "createInventorySlot") { // Erwartete Signatur: createInventorySlot(data: { backpackRefItem: BackpackRefItemEntity; character: CharacterEntity; item: ItemEntity; slotNumber: number; }) const params = method.value.params; if (!params || params.length !== 1) { context.report({ node: method, messageId: "invalidGenericMethodSignature", data: { methodName: "createInventorySlot", expectedSignature: "createInventorySlot(data: { backpackRefItem: BackpackRefItemEntity; character: CharacterEntity; item: ItemEntity; slotNumber: number; })" } }); } } }); } } }, }; }, };