mirror of
				https://github.com/lingble/twenty.git
				synced 2025-10-30 20:27:55 +00:00 
			
		
		
		
	 8483cf0b4b
			
		
	
	8483cf0b4b
	
	
	
		
			
			* chore: use Nx workspace lint rules Closes #3162 * Fix lint * Fix lint on BE * Fix tests --------- Co-authored-by: Charles Bochet <charles@twenty.com>
		
			
				
	
	
		
			143 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {
 | |
|   AST_NODE_TYPES,
 | |
|   ESLintUtils,
 | |
|   TSESTree,
 | |
| } from '@typescript-eslint/utils';
 | |
| import { isIdentifier } from '@typescript-eslint/utils/ast-utils';
 | |
| 
 | |
| // NOTE: The rule will be available in ESLint configs as "@nx/workspace-matching-state-variable"
 | |
| export const RULE_NAME = 'matching-state-variable';
 | |
| 
 | |
| export const rule = ESLintUtils.RuleCreator(() => __filename)({
 | |
|   name: RULE_NAME,
 | |
|   meta: {
 | |
|     type: 'problem',
 | |
|     docs: {
 | |
|       description:
 | |
|         'Ensure recoil value and setter are named after their atom name',
 | |
|       recommended: 'recommended',
 | |
|     },
 | |
|     fixable: 'code',
 | |
|     schema: [],
 | |
|     messages: {
 | |
|       invalidVariableName:
 | |
|         "Invalid usage of {{ hookName }}: the variable should be named '{{ expectedName }}' but found '{{ actualName }}'.",
 | |
|       invalidSetterName:
 | |
|         "Invalid usage of {{ hookName }}: Expected setter '{{ expectedName }}' but found '{{ actualName }}'.",
 | |
|     },
 | |
|   },
 | |
|   defaultOptions: [],
 | |
|   create: (context) => {
 | |
|     return {
 | |
|       VariableDeclarator: (node: TSESTree.VariableDeclarator) => {
 | |
|         if (
 | |
|           node?.init?.type === AST_NODE_TYPES.CallExpression &&
 | |
|           isIdentifier(node.init.callee) &&
 | |
|           [
 | |
|             'useRecoilState',
 | |
|             'useRecoilScopedState',
 | |
|             'useRecoilFamilyState',
 | |
|             'useRecoilScopedFamilyState',
 | |
|             'useRecoilValue',
 | |
|             'useRecoilScopedValue',
 | |
|           ].includes(node.init.callee.name)
 | |
|         ) {
 | |
|           const stateNameBase = isIdentifier(node.init.arguments[0])
 | |
|             ? node.init.arguments[0].name
 | |
|             : undefined;
 | |
| 
 | |
|           if (!stateNameBase) {
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|           const expectedVariableNameBase = stateNameBase.replace(
 | |
|             /(State|FamilyState|Selector|ScopedState|ScopedFamilyState|ScopedSelector)$/,
 | |
|             '',
 | |
|           );
 | |
| 
 | |
|           if (isIdentifier(node.id)) {
 | |
|             const actualVariableName = node.id.name;
 | |
| 
 | |
|             if (actualVariableName !== expectedVariableNameBase) {
 | |
|               context.report({
 | |
|                 node,
 | |
|                 messageId: 'invalidVariableName',
 | |
|                 data: {
 | |
|                   actualName: actualVariableName,
 | |
|                   expectedName: expectedVariableNameBase,
 | |
|                   hookName: stateNameBase,
 | |
|                   callee: node.init.callee.name,
 | |
|                 },
 | |
|                 fix: (fixer) => {
 | |
|                   return fixer.replaceText(node.id, expectedVariableNameBase);
 | |
|                 },
 | |
|               });
 | |
|             }
 | |
| 
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|           if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
 | |
|             const actualVariableName =
 | |
|               node.id.elements?.[0]?.type === AST_NODE_TYPES.Identifier
 | |
|                 ? node.id.elements[0].name
 | |
|                 : undefined;
 | |
| 
 | |
|             if (
 | |
|               actualVariableName &&
 | |
|               actualVariableName !== expectedVariableNameBase
 | |
|             ) {
 | |
|               context.report({
 | |
|                 node,
 | |
|                 messageId: 'invalidVariableName',
 | |
|                 data: {
 | |
|                   actual: actualVariableName,
 | |
|                   expected: expectedVariableNameBase,
 | |
|                   callee: node.init.callee.name,
 | |
|                 },
 | |
|                 fix: (fixer) => {
 | |
|                   if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
 | |
|                     return fixer.replaceText(
 | |
|                       node.id.elements[0] as TSESTree.Node,
 | |
|                       expectedVariableNameBase,
 | |
|                     );
 | |
|                   }
 | |
|                   return null;
 | |
|                 },
 | |
|               });
 | |
|             }
 | |
| 
 | |
|             if (isIdentifier(node.id.elements[1])) {
 | |
|               const actualSetterName = node.id.elements[1].name;
 | |
|               const expectedSetterName = `set${expectedVariableNameBase
 | |
|                 .charAt(0)
 | |
|                 .toUpperCase()}${expectedVariableNameBase.slice(1)}`;
 | |
| 
 | |
|               if (actualSetterName !== expectedSetterName) {
 | |
|                 context.report({
 | |
|                   node,
 | |
|                   messageId: 'invalidSetterName',
 | |
|                   data: {
 | |
|                     hookName: stateNameBase,
 | |
|                     actualName: actualSetterName,
 | |
|                     expectedName: expectedSetterName,
 | |
|                   },
 | |
|                   fix: (fixer) => {
 | |
|                     if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
 | |
|                       return fixer.replaceText(
 | |
|                         node.id.elements[1]!,
 | |
|                         expectedSetterName,
 | |
|                       );
 | |
|                     }
 | |
|                     return null;
 | |
|                   },
 | |
|                 });
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       },
 | |
|     };
 | |
|   },
 | |
| });
 |