eslint rules
This commit is contained in:
91
apps/website/eslint-rules/view-data-implements.js
Normal file
91
apps/website/eslint-rules/view-data-implements.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* ESLint rule to enforce ViewData contract implementation
|
||||
*
|
||||
* ViewData files in lib/view-data/ must:
|
||||
* 1. Be interfaces or types named *ViewData
|
||||
* 2. Extend the ViewData interface from contracts
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Enforce ViewData contract implementation',
|
||||
category: 'Contracts',
|
||||
recommended: true,
|
||||
},
|
||||
fixable: null,
|
||||
schema: [],
|
||||
messages: {
|
||||
notAnInterface: 'ViewData files must be interfaces or types named *ViewData',
|
||||
missingExtends: 'ViewData must extend the ViewData interface from lib/contracts/view-data/ViewData.ts',
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const filename = context.getFilename();
|
||||
const isInViewData = filename.includes('/lib/view-data/');
|
||||
|
||||
if (!isInViewData) return {};
|
||||
|
||||
let hasViewDataExtends = false;
|
||||
let hasCorrectName = false;
|
||||
|
||||
return {
|
||||
// Check interface declarations
|
||||
TSInterfaceDeclaration(node) {
|
||||
const interfaceName = node.id?.name;
|
||||
|
||||
if (interfaceName && interfaceName.endsWith('ViewData')) {
|
||||
hasCorrectName = true;
|
||||
|
||||
// Check if it extends ViewData
|
||||
if (node.extends && node.extends.length > 0) {
|
||||
for (const ext of node.extends) {
|
||||
if (ext.type === 'TSExpressionWithTypeArguments' &&
|
||||
ext.expression.type === 'Identifier' &&
|
||||
ext.expression.name === 'ViewData') {
|
||||
hasViewDataExtends = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Check type alias declarations
|
||||
TSTypeAliasDeclaration(node) {
|
||||
const typeName = node.id?.name;
|
||||
|
||||
if (typeName && typeName.endsWith('ViewData')) {
|
||||
hasCorrectName = true;
|
||||
|
||||
// For type aliases, check if it's an intersection with ViewData
|
||||
if (node.typeAnnotation && node.typeAnnotation.type === 'TSIntersectionType') {
|
||||
for (const type of node.typeAnnotation.types) {
|
||||
if (type.type === 'TSTypeReference' &&
|
||||
type.typeName &&
|
||||
type.typeName.type === 'Identifier' &&
|
||||
type.typeName.name === 'ViewData') {
|
||||
hasViewDataExtends = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'Program:exit'() {
|
||||
if (!hasCorrectName) {
|
||||
context.report({
|
||||
node: context.getSourceCode().ast,
|
||||
messageId: 'notAnInterface',
|
||||
});
|
||||
} else if (!hasViewDataExtends) {
|
||||
context.report({
|
||||
node: context.getSourceCode().ast,
|
||||
messageId: 'missingExtends',
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user