/** * ESLint Rule: Mutation Contract * * Ensures mutations return Result type */ module.exports = { meta: { type: 'problem', docs: { description: 'Ensure mutations return Result type', category: 'Mutation Contract', recommended: true, }, messages: { wrongReturnType: 'Mutations must return Promise> - see apps/website/lib/contracts/Result.ts', }, schema: [], }, create(context) { const filename = context.getFilename(); // Only apply to mutation files if (!filename.includes('/lib/mutations/') || !filename.endsWith('.ts')) { return {}; } return { MethodDefinition(node) { if (node.key.type === 'Identifier' && node.key.name === 'execute' && node.value.type === 'FunctionExpression') { const returnType = node.value.returnType; // Check if it returns Promise> if (!returnType || !returnType.typeAnnotation || !returnType.typeAnnotation.typeName || returnType.typeAnnotation.typeName.name !== 'Promise') { context.report({ node, messageId: 'wrongReturnType', }); return; } // Check for Result type const typeArgs = returnType.typeAnnotation.typeParameters; if (!typeArgs || !typeArgs.params || typeArgs.params.length === 0) { context.report({ node, messageId: 'wrongReturnType', }); return; } const resultType = typeArgs.params[0]; if (resultType.type !== 'TSTypeReference' || !resultType.typeName || (resultType.typeName.type === 'Identifier' && resultType.typeName.name !== 'Result')) { context.report({ node, messageId: 'wrongReturnType', }); } } }, }; }, };