Files
Netcatty/eslint.config.js

199 lines
6.1 KiB
JavaScript

import js from "@eslint/js";
import tsParser from "@typescript-eslint/parser";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import unusedImports from "eslint-plugin-unused-imports";
import reactHooks from "eslint-plugin-react-hooks";
import globals from "globals";
export default [
// The recommended preset has no file scope of its own, so scope it off all of
// electron/ — that main-process tree is historically unlinted. The bridges
// get a focused rule set in the dedicated block at the end of this config;
// every other electron/ file matches no config and stays unlinted as before.
{ ...js.configs.recommended, ignores: ["electron/**"] },
{
ignores: ["node_modules/**", "dist/**", "scripts/**", "public/monaco/**", ".github/**", ".claude/**", "release/**", ".worktrees/**"],
},
{
files: ["**/*.{ts,tsx}"],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
globals: {
// Browser globals
window: "readonly",
document: "readonly",
navigator: "readonly",
console: "readonly",
setTimeout: "readonly",
clearTimeout: "readonly",
setInterval: "readonly",
clearInterval: "readonly",
requestAnimationFrame: "readonly",
cancelAnimationFrame: "readonly",
fetch: "readonly",
URL: "readonly",
URLSearchParams: "readonly",
FormData: "readonly",
Blob: "readonly",
File: "readonly",
FileReader: "readonly",
AbortController: "readonly",
AbortSignal: "readonly",
Event: "readonly",
EventTarget: "readonly",
CustomEvent: "readonly",
MouseEvent: "readonly",
KeyboardEvent: "readonly",
DragEvent: "readonly",
ClipboardEvent: "readonly",
HTMLElement: "readonly",
HTMLInputElement: "readonly",
HTMLTextAreaElement: "readonly",
HTMLButtonElement: "readonly",
HTMLDivElement: "readonly",
HTMLFormElement: "readonly",
Element: "readonly",
Node: "readonly",
NodeList: "readonly",
MutationObserver: "readonly",
ResizeObserver: "readonly",
IntersectionObserver: "readonly",
localStorage: "readonly",
sessionStorage: "readonly",
crypto: "readonly",
performance: "readonly",
confirm: "readonly",
alert: "readonly",
prompt: "readonly",
getComputedStyle: "readonly",
atob: "readonly",
btoa: "readonly",
// Node.js globals (for Electron)
process: "readonly",
global: "readonly",
Buffer: "readonly",
__dirname: "readonly",
__filename: "readonly",
module: "readonly",
require: "readonly",
exports: "readonly",
},
},
plugins: {
"@typescript-eslint": tsPlugin,
"unused-imports": unusedImports,
"react-hooks": reactHooks,
},
rules: {
// Disable base rules that conflict with TypeScript
"no-unused-vars": "off",
"no-undef": "off", // TypeScript handles this
// TypeScript unused vars (disabled in favor of unused-imports)
"@typescript-eslint/no-unused-vars": "off",
// Disallow any type
"@typescript-eslint/no-explicit-any": "error",
// Unused imports plugin - this is the main feature you want
"unused-imports/no-unused-imports": "warn",
"unused-imports/no-unused-vars": [
"warn",
{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_",
},
],
// React Hooks rules
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
// Downgrade some rules to warnings (less critical)
"no-empty": "warn",
"no-useless-escape": "warn",
"no-case-declarations": "warn",
},
},
{
files: ["**/*.{ts,tsx}"],
rules: {
"no-restricted-properties": [
"error",
{
object: "window",
property: "netcatty",
message:
"Do not access window.netcatty directly; use netcattyBridge or an application/state backend hook.",
},
],
"no-restricted-globals": ["error", "localStorage", "sessionStorage"],
},
},
{
files: ["infrastructure/services/netcattyBridge.ts"],
rules: {
"no-restricted-properties": "off",
},
},
{
files: ["infrastructure/persistence/localStorageAdapter.ts"],
rules: {
"no-restricted-globals": "off",
},
},
{
files: ["components/**/*.{ts,tsx}"],
rules: {
"no-restricted-imports": [
"error",
{
patterns: [
{
group: [
"../infrastructure/persistence/*",
"../infrastructure/services/*",
"../../infrastructure/persistence/*",
"../../infrastructure/services/*",
],
message:
"Components should not import infrastructure persistence/services; use application/state hooks instead.",
},
],
},
],
},
},
{
// Electron main-process bridges are CommonJS and were historically excluded
// from linting. Lint them for undefined references only — the cheap,
// high-value guard against e.g. a removed variable still referenced
// elsewhere. (The TS config disables no-undef because the type-checker
// already covers it there; these .cjs files have no such safety net.)
files: ["electron/bridges/**/*.cjs"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "commonjs",
globals: globals.node,
},
linterOptions: {
// Only no-undef is enabled here, so pre-existing eslint-disable comments
// for other rules (no-console, no-control-regex, …) would all report as
// "unused". Don't flag them — they stay valid for future rule additions.
reportUnusedDisableDirectives: "off",
},
rules: {
"no-undef": "error",
},
},
];