import js from "@eslint/js"; import globals from "globals"; import tseslint from "typescript-eslint"; import reactHooks from "eslint-plugin-react-hooks"; import reactRefresh from "eslint-plugin-react-refresh"; export default tseslint.config( { ignores: [ "**/dist/**", "**/node_modules/**", "**/release/**", "client/public/**", // The packager's output, and the generated half of an app (Locadora's // vendored, patched emulator frontend and cores land in apps/*/public). "dist-apps/**", "apps/*/public/**", // a browser page that stands in for the pqp host in an app's e2e test "apps/*/e2e/host/**", "**/*.tsbuildinfo", // `wrangler dev` writes a bundled copy of the Worker here. It is // generated, it is git-ignored, and linting it fails the whole run for // anybody who has ever run the admin dashboard locally. "**/.wrangler/**", // VitePress's dependency-optimizer cache, git-ignored and generated. "**/.vitepress/cache/**", // The desktop share smoke test's built page and its results, both // generated and git-ignored (electron/test/share-smoke/). "electron/test/share-smoke/.page/**", "electron/test-results/**", ], }, js.configs.recommended, ...tseslint.configs.recommended, { files: ["**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2022, sourceType: "module", }, rules: { // Underscore-prefixed args are the codebase's "intentionally unused" marker. "@typescript-eslint/no-unused-vars": [ "error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, ], "@typescript-eslint/no-explicit-any": "error", "no-console": ["warn", { allow: ["warn", "error"] }], eqeqeq: ["error", "always", { null: "ignore" }], }, }, { files: ["client/src/**/*.{ts,tsx}"], languageOptions: { globals: globals.browser, }, plugins: { "react-hooks": reactHooks, "react-refresh": reactRefresh, }, rules: { // The `eslint-disable react-hooks/exhaustive-deps` comments in this // codebase referenced a rule that was never installed; it is real now. ...reactHooks.configs.recommended.rules, "react-refresh/only-export-components": "off", }, }, { files: ["server/src/**/*.ts", "packages/shared/src/**/*.ts"], languageOptions: { globals: globals.node, }, rules: { // Server logging is the intended observability channel here. "no-console": "off", }, }, { files: ["**/*.test.ts", "**/*.test.tsx"], rules: { "@typescript-eslint/no-explicit-any": "off", "no-console": "off", }, }, { // Ambient declaration files exist to be merged into, so every name in them // reads as unused. files: ["**/*.d.ts"], rules: { "@typescript-eslint/no-unused-vars": "off", }, }, { // Standalone Node ESM tooling, run with `node scripts/…`. `tools/**` is // the same shape one directory over: services that live in the repo but // outside the pnpm workspace, with their own install and their own entry // point (see `tools/ambient`). files: [ "scripts/**/*.mjs", "packages/app-sdk/scripts/**/*.mjs", "client/scripts/**/*.mjs", "server/scripts/**/*.mjs", "client/bench/**/*.mjs", "client/e2e/bandwidth/**/*.mjs", "client/e2e/share-audio-echo/**/*.mjs", "client/e2e/camera-sync/**/*.mjs", "client/e2e/share-fast-start/**/*.mjs", "client/e2e/desktop-share/**/*.mjs", "electron/**/*.mjs", "flatpak/**/*.mjs", "tools/**/*.{js,mjs}", "*.mjs", ], languageOptions: { // Benchmarks are Node scripts that also evaluate code inside a browser // page, so both sets of globals are legitimately in scope. globals: { ...globals.node, ...globals.browser, WebSocket: "readonly", fetch: "readonly", }, sourceType: "module", }, rules: { "no-console": "off", }, }, { // The Electron main process is CommonJS by design. files: ["electron/**/*.js"], languageOptions: { globals: globals.node, sourceType: "commonjs", }, rules: { "no-console": "off", "@typescript-eslint/no-require-imports": "off", }, }, { // `electron/picker/picker.js` is the one file under electron/ that runs in // a renderer rather than in Node: it is the share picker's page, loaded // from a plain `