2026-05-12 22:24:51 +02:00
|
|
|
import nextCoreWebVitals from 'eslint-config-next/core-web-vitals';
|
|
|
|
|
import prettier from 'eslint-config-prettier/flat';
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
|
|
|
|
|
const eslintConfig = [
|
2026-05-12 22:24:51 +02:00
|
|
|
...nextCoreWebVitals,
|
|
|
|
|
prettier,
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
{
|
2026-05-14 16:03:37 +02:00
|
|
|
// Scope the typescript-eslint rule overrides to TS/TSX files. Without
|
|
|
|
|
// the `files` filter, eslint flat-config attempts to apply these
|
|
|
|
|
// rules to every walked file (including root-level JS / mjs / json
|
|
|
|
|
// configs) and fails because the typescript-eslint plugin only
|
|
|
|
|
// registers itself for TS/TSX. Surfaced 2026-05-14 when CI's
|
|
|
|
|
// `pnpm lint` command ran across the whole repo root.
|
|
|
|
|
files: ['**/*.ts', '**/*.tsx'],
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
rules: {
|
2026-05-12 22:24:51 +02:00
|
|
|
'@typescript-eslint/no-explicit-any': 'error',
|
|
|
|
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
fix(compiler): React Compiler safety triage — 5 categories cleared
Cleared 4 rule buckets (37 violations, including 5 real bugs) and
silenced 1 informational bucket from the Next 16 / react-hooks v7
upgrade. Cleared rules promoted from `warn` back to `error` so new
regressions block CI.
Real bug fixes:
- `interest-contact-log-tab.tsx`: `useMemo` used for side effects
(5 setState calls inside a memo body); converted to `useEffect`.
- `PieChart.tsx`: cumulative `let angle` mutation in a render-phase
`map`; converted to `reduce` so the slice array is built without
re-assignment.
- `documents-hub.tsx`: `useMemo(() => ({ count: 0 }))` used as a
mutable drag counter; converted to `useRef`.
- `notes-list.tsx`: `Date.now()` read during render for note-edit
countdown (impure) → pinned to a `now` state ticked every 30s.
- `onboarding-checklist.tsx` / `user-profile.tsx` /
`user-settings.tsx`: `useEffect(() => void load(), [])` with the
`load` function declared AFTER the effect — relied on hoisting,
trips Compiler's "access before declared" rule. Declared inside
the effect.
Pattern fixes (intentional cache-via-ref → state or layout-effect):
- 6 `ref.current = x` writes during render moved into layout
effects (`use-realtime-invalidation`, `settings-form-card`,
`inbox`).
- 3 `ref.current` reads during render (search totals cache,
scanner file ref) rewritten to backed-by-state.
- `use-is-mobile.ts` rewritten on `useSyncExternalStore` to avoid
the SSR-then-rehydrate setState dance.
- `use-notifications.ts` rewritten to write socket pushes directly
into the React Query cache via `setQueryData`, removing a local
state mirror.
Rule config (`eslint.config.mjs`):
- `react-hooks/purity` → error (was warn, cleared)
- `react-hooks/set-state-in-render` → error (was warn, cleared)
- `react-hooks/immutability` → error (was warn, cleared)
- `react-hooks/refs` → error (was warn, cleared)
- `react-hooks/incompatible-library` → off (informational only)
- `react-hooks/set-state-in-effect` → warn (51 remaining, all the
useEffect→fetch→setState data-fetch pattern; migration to
useQuery tracked in BACKLOG)
Verified: tsc clean, eslint 0 errors / 69 warnings (down from 105),
vitest 1315/1315, next build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 23:14:16 +02:00
|
|
|
// React Compiler safety rules shipped with eslint-config-next@16 /
|
2026-05-13 11:50:07 +02:00
|
|
|
// react-hooks@7. Triage status (2026-05-13 sweep):
|
|
|
|
|
// purity, set-state-in-render, immutability, refs,
|
|
|
|
|
// set-state-in-effect — promoted to error after the cleanup
|
|
|
|
|
// sweep (Wave 3 of the 2026-05-12 audit). All hits migrated to
|
|
|
|
|
// either useQuery, render-phase derivation, key-based remount,
|
|
|
|
|
// or a justified eslint-disable for canonical setState-on-
|
|
|
|
|
// subscription patterns. New regressions block CI.
|
fix(compiler): React Compiler safety triage — 5 categories cleared
Cleared 4 rule buckets (37 violations, including 5 real bugs) and
silenced 1 informational bucket from the Next 16 / react-hooks v7
upgrade. Cleared rules promoted from `warn` back to `error` so new
regressions block CI.
Real bug fixes:
- `interest-contact-log-tab.tsx`: `useMemo` used for side effects
(5 setState calls inside a memo body); converted to `useEffect`.
- `PieChart.tsx`: cumulative `let angle` mutation in a render-phase
`map`; converted to `reduce` so the slice array is built without
re-assignment.
- `documents-hub.tsx`: `useMemo(() => ({ count: 0 }))` used as a
mutable drag counter; converted to `useRef`.
- `notes-list.tsx`: `Date.now()` read during render for note-edit
countdown (impure) → pinned to a `now` state ticked every 30s.
- `onboarding-checklist.tsx` / `user-profile.tsx` /
`user-settings.tsx`: `useEffect(() => void load(), [])` with the
`load` function declared AFTER the effect — relied on hoisting,
trips Compiler's "access before declared" rule. Declared inside
the effect.
Pattern fixes (intentional cache-via-ref → state or layout-effect):
- 6 `ref.current = x` writes during render moved into layout
effects (`use-realtime-invalidation`, `settings-form-card`,
`inbox`).
- 3 `ref.current` reads during render (search totals cache,
scanner file ref) rewritten to backed-by-state.
- `use-is-mobile.ts` rewritten on `useSyncExternalStore` to avoid
the SSR-then-rehydrate setState dance.
- `use-notifications.ts` rewritten to write socket pushes directly
into the React Query cache via `setQueryData`, removing a local
state mirror.
Rule config (`eslint.config.mjs`):
- `react-hooks/purity` → error (was warn, cleared)
- `react-hooks/set-state-in-render` → error (was warn, cleared)
- `react-hooks/immutability` → error (was warn, cleared)
- `react-hooks/refs` → error (was warn, cleared)
- `react-hooks/incompatible-library` → off (informational only)
- `react-hooks/set-state-in-effect` → warn (51 remaining, all the
useEffect→fetch→setState data-fetch pattern; migration to
useQuery tracked in BACKLOG)
Verified: tsc clean, eslint 0 errors / 69 warnings (down from 105),
vitest 1315/1315, next build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 23:14:16 +02:00
|
|
|
// incompatible-library — informational only ("Compiler
|
|
|
|
|
// skipped this file because of a non-Compiler-safe import").
|
|
|
|
|
// No action needed; silenced to keep `pnpm lint` output
|
|
|
|
|
// actionable.
|
|
|
|
|
'react-hooks/purity': 'error',
|
|
|
|
|
'react-hooks/set-state-in-render': 'error',
|
|
|
|
|
'react-hooks/immutability': 'error',
|
|
|
|
|
'react-hooks/refs': 'error',
|
2026-05-13 11:50:07 +02:00
|
|
|
'react-hooks/set-state-in-effect': 'error',
|
fix(compiler): React Compiler safety triage — 5 categories cleared
Cleared 4 rule buckets (37 violations, including 5 real bugs) and
silenced 1 informational bucket from the Next 16 / react-hooks v7
upgrade. Cleared rules promoted from `warn` back to `error` so new
regressions block CI.
Real bug fixes:
- `interest-contact-log-tab.tsx`: `useMemo` used for side effects
(5 setState calls inside a memo body); converted to `useEffect`.
- `PieChart.tsx`: cumulative `let angle` mutation in a render-phase
`map`; converted to `reduce` so the slice array is built without
re-assignment.
- `documents-hub.tsx`: `useMemo(() => ({ count: 0 }))` used as a
mutable drag counter; converted to `useRef`.
- `notes-list.tsx`: `Date.now()` read during render for note-edit
countdown (impure) → pinned to a `now` state ticked every 30s.
- `onboarding-checklist.tsx` / `user-profile.tsx` /
`user-settings.tsx`: `useEffect(() => void load(), [])` with the
`load` function declared AFTER the effect — relied on hoisting,
trips Compiler's "access before declared" rule. Declared inside
the effect.
Pattern fixes (intentional cache-via-ref → state or layout-effect):
- 6 `ref.current = x` writes during render moved into layout
effects (`use-realtime-invalidation`, `settings-form-card`,
`inbox`).
- 3 `ref.current` reads during render (search totals cache,
scanner file ref) rewritten to backed-by-state.
- `use-is-mobile.ts` rewritten on `useSyncExternalStore` to avoid
the SSR-then-rehydrate setState dance.
- `use-notifications.ts` rewritten to write socket pushes directly
into the React Query cache via `setQueryData`, removing a local
state mirror.
Rule config (`eslint.config.mjs`):
- `react-hooks/purity` → error (was warn, cleared)
- `react-hooks/set-state-in-render` → error (was warn, cleared)
- `react-hooks/immutability` → error (was warn, cleared)
- `react-hooks/refs` → error (was warn, cleared)
- `react-hooks/incompatible-library` → off (informational only)
- `react-hooks/set-state-in-effect` → warn (51 remaining, all the
useEffect→fetch→setState data-fetch pattern; migration to
useQuery tracked in BACKLOG)
Verified: tsc clean, eslint 0 errors / 69 warnings (down from 105),
vitest 1315/1315, next build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 23:14:16 +02:00
|
|
|
'react-hooks/incompatible-library': 'off',
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
},
|
|
|
|
|
},
|
2026-05-12 18:16:18 +02:00
|
|
|
{
|
|
|
|
|
// Tests assert response shape via expect() — narrowing every
|
|
|
|
|
// `res.json()` to a structural type adds boilerplate without catching
|
2026-05-14 16:03:37 +02:00
|
|
|
// bugs. Allow `any` casts at JSON boundaries in test files. Also
|
|
|
|
|
// relax unused-vars to warn (destructured-but-unused helpers are
|
|
|
|
|
// common in setup/teardown patterns).
|
2026-05-12 22:24:51 +02:00
|
|
|
files: ['tests/**/*.ts', 'tests/**/*.tsx'],
|
2026-05-12 18:16:18 +02:00
|
|
|
rules: {
|
2026-05-12 22:24:51 +02:00
|
|
|
'@typescript-eslint/no-explicit-any': 'off',
|
2026-05-14 16:03:37 +02:00
|
|
|
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
2026-05-12 18:16:18 +02:00
|
|
|
},
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
{
|
2026-05-14 16:03:37 +02:00
|
|
|
ignores: [
|
|
|
|
|
'client-portal/**',
|
|
|
|
|
'next-env.d.ts',
|
|
|
|
|
// Agent worktree artifacts — not part of the canonical tree.
|
|
|
|
|
'.claude/**',
|
|
|
|
|
// Build output + Next generated types
|
|
|
|
|
'.next/**',
|
|
|
|
|
'dist/**',
|
|
|
|
|
// Other sub-projects with their own toolchains
|
|
|
|
|
'website/**',
|
|
|
|
|
],
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export default eslintConfig;
|