import { defineConfig, globalIgnores } from 'eslint/config'; import nextVitals from 'eslint-config-next/core-web-vitals'; const eslintConfig = defineConfig([ ...nextVitals, globalIgnores([ '.next/**', 'node_modules/**', 'out/**', 'build/**', 'next-env.d.ts', 'scripts/migrations/**', ]), // The flat config from `eslint-config-next/core-web-vitals` does NOT // enable the core `no-undef` rule for plain-JS identifier references // — only `react/jsx-no-undef`, which catches undefined JSX components // but NOT plain function/variable references like `useFocusTrap(...)` // in a hook call. PR #144 (`31da384`) shipped a runtime // ReferenceError to production because of this gap; that bug would // have been caught at lint time with the rule on. We enable it // directly rather than pulling in `@eslint/js/recommended` (which // would also turn on `no-unused-vars`, `no-prototype-builtins`, and // a handful of others that surface a flood of pre-existing // violations and risk derailing this hotfix-class change). // // Browser + Node globals (window, document, process, Buffer, etc.) // are sourced from the language-options block below. { rules: { 'no-undef': 'error', }, languageOptions: { globals: { // Browser window: 'readonly', document: 'readonly', navigator: 'readonly', fetch: 'readonly', FormData: 'readonly', File: 'readonly', Blob: 'readonly', URL: 'readonly', URLSearchParams: 'readonly', localStorage: 'readonly', sessionStorage: 'readonly', location: 'readonly', history: 'readonly', alert: 'readonly', confirm: 'readonly', prompt: 'readonly', atob: 'readonly', btoa: 'readonly', crypto: 'readonly', WebSocket: 'readonly', Image: 'readonly', MediaStream: 'readonly', MediaStreamTrack: 'readonly', ImageCapture: 'readonly', MediaRecorder: 'readonly', AbortController: 'readonly', Event: 'readonly', CustomEvent: 'readonly', HTMLElement: 'readonly', HTMLInputElement: 'readonly', HTMLImageElement: 'readonly', HTMLVideoElement: 'readonly', HTMLCanvasElement: 'readonly', Element: 'readonly', Node: 'readonly', NodeList: 'readonly', DOMException: 'readonly', IntersectionObserver: 'readonly', MutationObserver: 'readonly', ResizeObserver: 'readonly', requestAnimationFrame: 'readonly', cancelAnimationFrame: 'readonly', getComputedStyle: 'readonly', // Timers (shared between browser + node) setTimeout: 'readonly', clearTimeout: 'readonly', setInterval: 'readonly', clearInterval: 'readonly', queueMicrotask: 'readonly', // Console + globals console: 'readonly', globalThis: 'readonly', // Node / Next.js runtime process: 'readonly', Buffer: 'readonly', __dirname: 'readonly', __filename: 'readonly', module: 'readonly', require: 'readonly', exports: 'readonly', global: 'readonly', }, }, }, { files: ['scripts/**/*.js'], rules: { 'no-restricted-syntax': ['error', { selector: 'CallExpression[callee.name="require"]', message: 'Use ESM `import` syntax. `package.json` has "type": "module"; require() throws ReferenceError at runtime. See .convoys/fix-reset-db-script.md.', }], }, }, // Vitest test files have an additional set of globals (describe, it, // expect, vi, beforeEach, etc.). Defining them here keeps the test // files from triggering no-undef while leaving the rule strict for // source files. { files: ['test/**/*.js', '**/*.test.js', '**/*.test.ts', 'test/setup.js'], languageOptions: { globals: { describe: 'readonly', it: 'readonly', test: 'readonly', expect: 'readonly', vi: 'readonly', beforeEach: 'readonly', afterEach: 'readonly', beforeAll: 'readonly', afterAll: 'readonly', }, }, }, ]); export default eslintConfig;