website refactor
This commit is contained in:
@@ -25,11 +25,13 @@ const writeBoundaryRules = require('./write-boundary-rules');
|
|||||||
const modelTaxonomyRules = require('./model-taxonomy-rules');
|
const modelTaxonomyRules = require('./model-taxonomy-rules');
|
||||||
const filenameRules = require('./filename-rules');
|
const filenameRules = require('./filename-rules');
|
||||||
const componentNoDataManipulation = require('./component-no-data-manipulation');
|
const componentNoDataManipulation = require('./component-no-data-manipulation');
|
||||||
|
const presenterPurity = require('./presenter-purity');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
// Presenter Contract
|
// Presenter Contract
|
||||||
'presenter-contract': presenterContract,
|
'presenter-contract': presenterContract,
|
||||||
|
'presenter-purity': presenterPurity,
|
||||||
|
|
||||||
// RSC Boundary Rules
|
// RSC Boundary Rules
|
||||||
'rsc-no-container-manager': rscBoundaryRules['no-container-manager-in-server'],
|
'rsc-no-container-manager': rscBoundaryRules['no-container-manager-in-server'],
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ module.exports = {
|
|||||||
if (presenterClassNode &&
|
if (presenterClassNode &&
|
||||||
node.key.type === 'Identifier' &&
|
node.key.type === 'Identifier' &&
|
||||||
node.key.name === 'present' &&
|
node.key.name === 'present' &&
|
||||||
node.parent === presenterClassNode) {
|
node.parent.type === 'ClassBody' &&
|
||||||
|
node.parent.parent === presenterClassNode) {
|
||||||
hasPresentMethod = true;
|
hasPresentMethod = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
53
apps/website/eslint-rules/presenter-purity.js
Normal file
53
apps/website/eslint-rules/presenter-purity.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* ESLint rule: Presenters should only do pure mapping, not business logic
|
||||||
|
*
|
||||||
|
* Presenters should NOT use:
|
||||||
|
* - .filter() - filtering should happen in PageQuery
|
||||||
|
* - .sort() - sorting should happen in PageQuery
|
||||||
|
* - .reduce() - aggregation should happen in PageQuery
|
||||||
|
* - .find() - lookup should happen in PageQuery
|
||||||
|
* - .some() / .every() - checks should happen in PageQuery
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
meta: {
|
||||||
|
type: 'problem',
|
||||||
|
docs: {
|
||||||
|
description: 'Forbid business logic operations in presenters',
|
||||||
|
category: 'Presenter Purity',
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
message: 'Presenter should only do pure mapping. Move {{operation}}() to PageQuery - see apps/website/lib/contracts/presenters/Presenter.ts',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
return {
|
||||||
|
CallExpression(node) {
|
||||||
|
const filename = context.getFilename();
|
||||||
|
|
||||||
|
// Check if this is a presenter file
|
||||||
|
if (filename.includes('/lib/presenters/') && filename.endsWith('.ts')) {
|
||||||
|
|
||||||
|
// Check for business logic operations
|
||||||
|
if (node.callee.type === 'MemberExpression') {
|
||||||
|
const property = node.callee.property;
|
||||||
|
|
||||||
|
if (property.type === 'Identifier') {
|
||||||
|
const forbiddenOperations = ['filter', 'sort', 'reduce', 'find', 'some', 'every', 'map'];
|
||||||
|
const operation = property.name;
|
||||||
|
|
||||||
|
// Allow .map() - that's the core presenter operation
|
||||||
|
if (forbiddenOperations.includes(operation) && operation !== 'map') {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'message',
|
||||||
|
data: { operation },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user