harb/services/ponder/eslint.config.js

101 lines
3 KiB
JavaScript
Raw Normal View History

import eslint from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
import eslintConfigPrettier from 'eslint-config-prettier';
export default [
eslint.configs.recommended,
{
files: ['**/*.ts'],
languageOptions: {
parser: tsparser,
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: import.meta.dirname,
},
globals: {
process: 'readonly',
console: 'readonly',
Context: 'readonly',
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
// TypeScript
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'function',
format: ['camelCase'],
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE'],
},
{
selector: 'typeLike',
format: ['PascalCase'],
},
],
// Style
'prefer-const': 'error',
indent: ['error', 2, { SwitchCase: 1 }],
'max-len': [
'error',
{
code: 140,
ignoreStrings: true,
ignoreTemplateLiterals: true,
ignoreUrls: true,
},
],
// Console
'no-console': 'error',
// Complexity (off)
complexity: 'off',
'max-depth': 'off',
'max-nested-callbacks': 'off',
'max-params': 'off',
'max-statements': 'off',
},
},
{
name: 'arch/ponder-bounded-queries',
rules: {
'no-restricted-syntax': [
'error',
{
selector: "CallExpression[callee.property.name='findMany']:not(:has(Property[key.name='limit']))",
message:
"Ponder findMany() called without a limit parameter. Unbounded queries will grow without limit as the chain is indexed — never use findMany() without a limit. Always specify `limit` in the options object. Use the ring buffer pattern from docs/ARCHITECTURE.md.",
},
{
selector: "CallExpression[callee.property.name='waitForTimeout']",
message:
'[BANNED] waitForTimeout is a fixed delay. → Subscribe to events instead (eth_newFilter for on-chain, waitForSelector/waitForURL for DOM). → Polling with timeout is acceptable only if no event source exists. → See AGENTS.md #Engineering Principles.',
},
{
selector:
"NewExpression[callee.name='Promise'] > ArrowFunctionExpression CallExpression[callee.name='setTimeout']",
message:
'[BANNED] Promise+setTimeout sleep pattern. → Use event subscription or polling with timeout instead. → See AGENTS.md #Engineering Principles.',
},
],
},
},
eslintConfigPrettier,
];