Merge pull request #1297 from trycua/claude/add-eslint-preserve-error-YnKYj

Add ESLint configuration and fix linting issues
This commit is contained in:
gavrielc
2026-03-21 11:57:30 +02:00
committed by GitHub
12 changed files with 1429 additions and 17 deletions

32
eslint.config.js Normal file
View File

@@ -0,0 +1,32 @@
import globals from 'globals'
import pluginJs from '@eslint/js'
import tseslint from 'typescript-eslint'
import noCatchAll from 'eslint-plugin-no-catch-all'
export default [
{ ignores: ['node_modules/', 'dist/', 'container/', 'groups/'] },
{ files: ['src/**/*.{js,ts}'] },
{ languageOptions: { globals: globals.node } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
{
plugins: { 'no-catch-all': noCatchAll },
rules: {
'preserve-caught-error': ['error', { requireCatchParameter: true }],
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'no-catch-all/no-catch-all': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
},
},
]

1376
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,8 @@
"prepare": "husky",
"setup": "tsx setup/index.ts",
"auth": "tsx src/whatsapp-auth.ts",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"test": "vitest run",
"test:watch": "vitest"
},
@@ -27,13 +29,18 @@
"zod": "^4.3.6"
},
"devDependencies": {
"@eslint/js": "^9.35.0",
"@types/better-sqlite3": "^7.6.12",
"@types/node": "^22.10.0",
"@vitest/coverage-v8": "^4.0.18",
"eslint": "^9.35.0",
"eslint-plugin-no-catch-all": "^1.1.0",
"globals": "^15.12.0",
"husky": "^9.1.7",
"prettier": "^3.8.1",
"tsx": "^4.19.0",
"typescript": "^5.7.0",
"typescript-eslint": "^8.35.0",
"vitest": "^4.0.18"
},
"engines": {

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { describe, it, expect } from 'vitest';
import {
registerChannel,

View File

@@ -507,11 +507,7 @@ export async function runContainerAgent(
// Full input is only included at verbose level to avoid
// persisting user conversation content on every non-zero exit.
if (isVerbose) {
logLines.push(
`=== Input ===`,
JSON.stringify(input, null, 2),
``,
);
logLines.push(`=== Input ===`, JSON.stringify(input, null, 2), ``);
} else {
logLines.push(
`=== Input Summary ===`,
@@ -698,7 +694,7 @@ export function writeGroupsSnapshot(
groupFolder: string,
isMain: boolean,
groups: AvailableGroup[],
registeredJids: Set<string>,
_registeredJids: Set<string>,
): void {
const groupIpcDir = resolveGroupIpcPath(groupFolder);
fs.mkdirSync(groupIpcDir, { recursive: true });

View File

@@ -96,7 +96,9 @@ export function ensureContainerRuntimeRunning(): void {
console.error(
'╚════════════════════════════════════════════════════════════════╝\n',
);
throw new Error('Container runtime is required but failed to start');
throw new Error('Container runtime is required but failed to start', {
cause: err,
});
}
}

View File

@@ -40,7 +40,7 @@ describe('GroupQueue', () => {
let concurrentCount = 0;
let maxConcurrent = 0;
const processMessages = vi.fn(async (groupJid: string) => {
const processMessages = vi.fn(async (_groupJid: string) => {
concurrentCount++;
maxConcurrent = Math.max(maxConcurrent, concurrentCount);
// Simulate async work
@@ -69,7 +69,7 @@ describe('GroupQueue', () => {
let maxActive = 0;
const completionCallbacks: Array<() => void> = [];
const processMessages = vi.fn(async (groupJid: string) => {
const processMessages = vi.fn(async (_groupJid: string) => {
activeCount++;
maxActive = Math.max(maxActive, activeCount);
await new Promise<void>((resolve) => completionCallbacks.push(resolve));
@@ -104,7 +104,7 @@ describe('GroupQueue', () => {
const executionOrder: string[] = [];
let resolveFirst: () => void;
const processMessages = vi.fn(async (groupJid: string) => {
const processMessages = vi.fn(async (_groupJid: string) => {
if (executionOrder.length === 0) {
// First call: block until we release it
await new Promise<void>((resolve) => {

View File

@@ -351,7 +351,7 @@ export class GroupQueue {
// via idle timeout or container timeout. The --rm flag cleans them up on exit.
// This prevents WhatsApp reconnection restarts from killing working agents.
const activeContainers: string[] = [];
for (const [jid, state] of this.groups) {
for (const [_jid, state] of this.groups) {
if (state.process && !state.process.killed && state.containerName) {
activeContainers.push(state.containerName);
}

View File

@@ -33,7 +33,6 @@ import {
getAllTasks,
getMessagesSince,
getNewMessages,
getRegisteredGroup,
getRouterState,
initDatabase,
setRegisteredGroup,

View File

@@ -37,7 +37,7 @@ describe('remote-control', () => {
let readFileSyncSpy: ReturnType<typeof vi.spyOn>;
let writeFileSyncSpy: ReturnType<typeof vi.spyOn>;
let unlinkSyncSpy: ReturnType<typeof vi.spyOn>;
let mkdirSyncSpy: ReturnType<typeof vi.spyOn>;
let _mkdirSyncSpy: ReturnType<typeof vi.spyOn>;
let openSyncSpy: ReturnType<typeof vi.spyOn>;
let closeSyncSpy: ReturnType<typeof vi.spyOn>;
@@ -50,7 +50,7 @@ describe('remote-control', () => {
stdoutFileContent = '';
// Default fs mocks
mkdirSyncSpy = vi
_mkdirSyncSpy = vi
.spyOn(fs, 'mkdirSync')
.mockImplementation(() => undefined as any);
writeFileSyncSpy = vi

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { _initTestDatabase, getAllChats, storeChatMetadata } from './db.js';
import { _initTestDatabase, storeChatMetadata } from './db.js';
import { getAvailableGroups, _setRegisteredGroups } from './index.js';
beforeEach(() => {

View File

@@ -1,7 +1,7 @@
import fs from 'fs';
import os from 'os';
import path from 'path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import {
isSenderAllowed,