Ctrl K
ComunidadGuías…

eslint.config.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import js from '@eslint/js'
import globals from 'globals'
import reactPlugin from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import tseslint from 'typescript-eslint'

// Vitest injects these into the global scope (`globals: true` in every SPA's
// vite.config test block). The `globals` package has no vitest set, so name them.
const TEST_GLOBALS = {
  describe: 'readonly',
  it: 'readonly',
  test: 'readonly',
  expect: 'readonly',
  vi: 'readonly',
  vitest: 'readonly',
  beforeAll: 'readonly',
  afterAll: 'readonly',
  beforeEach: 'readonly',
  afterEach: 'readonly',
}

export default [
  {
    // Build output, vendored code, and trees other seats own. `eslint .` from
    // the repo root would otherwise reach into the Python package and the
    // clients/ workspaces. The Desktop track lints `clients/desktop/**/*.ts`
    // via the appended block near the end of this file; everything else under
    // `clients/` stays out (the Rust/Tauri crate, the VR client).
    ignores: [
      '**/dist/**',
      '**/build/**',
      '**/coverage/**',
      '**/node_modules/**',
      // Workspace-local board/skill code and generated review/staging
      // artifacts are private tooling, not repository lint targets. A local
      // `eslint .` should match the clean-checkout CI surface.
      '.agents/**',
      '.artifacts/**',
      'docs/_private/**',
      // Local Python virtualenvs ship bundled JS (werkzeug debugger, urllib3
      // emscripten worker) that `eslint .` would otherwise lint. CI has no venv;
      // ignore it so `npm run lint` matches CI when run in a dev checkout.
      '**/venv/**',
      '**/.venv/**',
      '**/*.min.js',
      'oneirodex/**',
      'scripts/**',
      'clients/quest/**',
      'clients/desktop/src-tauri/**',
      // Standalone node harnesses for the classic (Jinja) theme JS. CI runs
      // them with `node` directly; they are not part of any SPA and predate
      // this seat's scope.
      'tests/**',
      // Generated — the source of truth is scripts/gen_loading_motifs.py.
      'frontend/member-app/src/components/systemMotifCatalogue.ts',
    ],
  },

  js.configs.recommended,

  // Member / admin / ops React SPAs, plus the shared frontend modules.
  {
    files: ['frontend/**/*.{js,jsx,mjs,cjs}'],
    languageOptions: {
      ecmaVersion: 2023,
      sourceType: 'module',
      parserOptions: { ecmaFeatures: { jsx: true } },
      globals: { ...globals.browser },
    },
    plugins: { react: reactPlugin, 'react-hooks': reactHooks },
    settings: { react: { version: 'detect' } },
    rules: {
      ...reactPlugin.configs.flat.recommended.rules,
      ...reactPlugin.configs.flat['jsx-runtime'].rules,
      // rules-of-hooks catches real bugs — keep it hard. exhaustive-deps is
      // advisory (Phase 3 tightens it). The rest of react-hooks v7's compiler
      // ruleset is deliberately not enabled here.
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn',
      // The SPAs do not use PropTypes; TypeScript on-ramp (B0.3) is the type gate.
      'react/prop-types': 'off',
      // `_`-prefixed names are the codebase's "deliberately unused" marker
      // (e.g. `{ shellConfig: _shellConfig }`, `catch (_err)`).
      'no-unused-vars': [
        'warn',
        { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
      ],
      'no-undef': 'error',
    },
  },

  // Frontend test, setup, and Vite config files run under Node with Vitest
  // globals in scope.
  {
    files: [
      'frontend/**/*.{test,spec}.{js,jsx}',
      'frontend/**/testSetup.{js,ts}',
      'frontend/**/vite.config.js',
      'frontend/**/*.config.{js,mjs}',
    ],
    languageOptions: { globals: { ...globals.node, ...TEST_GLOBALS } },
  },

  // TypeScript surface owned by this seat: the shared API client. Uses
  // typescript-eslint's non-type-checked recommended set (no project graph, so
  // it stays fast). The Tauri companion (also TS) is linted from the Desktop
  // track with this same block shape.
  ...tseslint.config({
    files: ['frontend/api-client/**/*.{ts,tsx}'],
    extends: [tseslint.configs.recommended],
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
    rules: {
      '@typescript-eslint/no-unused-vars': 'warn',
      // Off on purpose: ~1,077 sites would drown the warnings that matter. The
      // gate is scripts/any_lint.mjs (per-file baseline, CI-run, only moves
      // down). Flip to 'error' when that baseline reaches 0.
      '@typescript-eslint/no-explicit-any': 'off',
      // tsc resolves identifiers and types; core no-undef only produces false
      // positives on a TS surface.
      'no-undef': 'off',
    },
  }),

  {
    files: ['frontend/api-client/**/*.{test,spec}.ts'],
    languageOptions: { globals: { ...TEST_GLOBALS } },
  },

  // TypeScript surface owned by this seat: `@oneirodex/ui` (frontend/shared),
  // ops-glance, and member-app (PR-5a). Same non-type-checked recommended set
  // as the api-client block above, plus the React plugins because these files
  // carry components/hooks.
  ...tseslint.config({
    files: [
      'frontend/shared/**/*.{ts,tsx}',
      'frontend/ops-glance/**/*.{ts,tsx}',
      'frontend/member-app/**/*.{ts,tsx}',
      'frontend/admin-app/**/*.{ts,tsx}',
    ],
    extends: [tseslint.configs.recommended],
    plugins: { react: reactPlugin, 'react-hooks': reactHooks },
    settings: { react: { version: 'detect' } },
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
    rules: {
      ...reactPlugin.configs.flat.recommended.rules,
      ...reactPlugin.configs.flat['jsx-runtime'].rules,
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn',
      'react/prop-types': 'off',
      '@typescript-eslint/no-unused-vars': [
        'warn',
        { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
      ],
      // Off on purpose: ~1,077 sites would drown the warnings that matter. The
      // gate is scripts/any_lint.mjs (per-file baseline, CI-run, only moves
      // down). Flip to 'error' when that baseline reaches 0.
      '@typescript-eslint/no-explicit-any': 'off',
      'no-undef': 'off',
    },
  }),

  // --- Desktop track (clients/desktop) --------------------------------------
  // Appended by the Desktop seat (wave C3.7-client / ci-wishlist [B0.2]).
  // Mirrors the frontend/api-client block: typescript-eslint's non-type-checked
  // recommended set over the Tauri companion's TS. Same rule tweaks so the two
  // TS surfaces lint identically.
  ...tseslint.config({
    files: ['clients/desktop/**/*.{ts,tsx}'],
    extends: [tseslint.configs.recommended],
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
    rules: {
      '@typescript-eslint/no-unused-vars': 'warn',
      // Off on purpose: ~1,077 sites would drown the warnings that matter. The
      // gate is scripts/any_lint.mjs (per-file baseline, CI-run, only moves
      // down). Flip to 'error' when that baseline reaches 0.
      '@typescript-eslint/no-explicit-any': 'off',
      'no-undef': 'off',
    },
  }),

  {
    files: ['clients/desktop/**/*.{test,spec}.ts'],
    languageOptions: { globals: { ...TEST_GLOBALS } },
  },

  // Repo-root tooling files (this config included).
  {
    files: ['*.js', '*.mjs'],
    languageOptions: { sourceType: 'module', globals: { ...globals.node } },
  },
]