website refactor
This commit is contained in:
94
apps/website/eslint-rules/client-only-rules.js
Normal file
94
apps/website/eslint-rules/client-only-rules.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* ESLint rules for Client-Only Guardrails
|
||||
*
|
||||
* Enforces client-side only boundaries
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// Rule 1: No server-side code in client-only files
|
||||
'no-server-code-in-client-only': {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Forbid server-side code in client-only files',
|
||||
category: 'Client-Only',
|
||||
},
|
||||
messages: {
|
||||
message: 'Client-only files cannot contain server-side code',
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
Program(node) {
|
||||
const filename = context.getFilename();
|
||||
if (filename.includes('/app/') &&
|
||||
filename.endsWith('.tsx') &&
|
||||
!filename.endsWith('page.tsx') &&
|
||||
!filename.endsWith('layout.tsx')) {
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
const text = sourceCode.getText();
|
||||
|
||||
// Check for server-side patterns
|
||||
const serverPatterns = [
|
||||
/getServerSideProps/,
|
||||
/cookies\(\)/,
|
||||
/headers\(\)/,
|
||||
/next\/headers/,
|
||||
];
|
||||
|
||||
for (const pattern of serverPatterns) {
|
||||
if (pattern.test(text)) {
|
||||
context.report({
|
||||
loc: { line: 1, column: 0 },
|
||||
messageId: 'message',
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
// Rule 2: Client-only files must have 'use client' directive
|
||||
'client-only-must-have-directive': {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Enforce use client directive',
|
||||
category: 'Client-Only',
|
||||
},
|
||||
messages: {
|
||||
message: 'Client-only files must have "use client" directive at the top',
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
Program(node) {
|
||||
const filename = context.getFilename();
|
||||
if (filename.includes('/app/') &&
|
||||
filename.endsWith('.tsx') &&
|
||||
!filename.endsWith('page.tsx') &&
|
||||
!filename.endsWith('layout.tsx')) {
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
const firstComment = sourceCode.getAllComments()[0];
|
||||
|
||||
const hasDirective = firstComment &&
|
||||
firstComment.type === 'Line' &&
|
||||
firstComment.value.trim() === '"use client"';
|
||||
|
||||
if (!hasDirective) {
|
||||
context.report({
|
||||
loc: { line: 1, column: 0 },
|
||||
messageId: 'message',
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user