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', setInterval: 'readonly', clearInterval: '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, ];