eslint.config.mjs
Rama main · réplica de lectura del repositorio original.
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";
/**
* Until v2.0.3 `npm run lint` was only `tsc --noEmit`, so nothing ever checked
* the rules TypeScript doesn't: exhaustive effect dependencies above all. Two
* `// eslint-disable-next-line react-hooks/exhaustive-deps` comments were sitting
* in the app suppressing a rule that wasn't installed to begin with -- and the
* bug that rule exists to catch is exactly the one that cost the simulator two
* fixes (see endpointDevice.ts).
*/
export default tseslint.config(
{ ignores: ["**/dist/**", "**/dist-demo/**", "**/node_modules/**", "**/*.tsbuildinfo"] },
// Every TypeScript file.
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: { ...globals.node },
},
rules: {
// The codebase marks deliberate unused bindings with a leading underscore
// (and uses rest-destructuring to drop a field).
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_", ignoreRestSiblings: true },
],
},
},
// The web app: browser globals plus the React rules.
{
files: ["apps/web/src/**/*.{ts,tsx}"],
plugins: { "react-hooks": reactHooks, "react-refresh": reactRefresh },
languageOptions: {
globals: { ...globals.browser },
parserOptions: { ecmaFeatures: { jsx: true } },
},
rules: {
...reactHooks.configs.recommended.rules,
// An ERROR, not the plugin's default warning: a stale dependency array is
// the exact failure mode that cost the simulator two bug fixes, so it
// should fail the build rather than scroll past in the output.
"react-hooks/exhaustive-deps": "error",
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
},
},
// The engine must stay free of server-only imports so it can run in the
// browser for the public demo. packages/engine/src/purity.test.ts asserts the
// same thing at test time; this is the version you see while you type.
{
files: ["packages/engine/src/**/*.ts"],
rules: {
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["node:*", "fs", "path", "os", "crypto", "http", "https", "dns", "child_process"],
message:
"The engine must stay I/O-free -- it runs in the browser for the public demo. Keep Node APIs in apps/server.",
},
{
group: ["@azure/*", "dotenv", "fastify", "@fastify/*"],
message: "Server-only dependency. The engine takes a TenantData; it never fetches one.",
},
],
},
],
},
},
// The Graph layer must stay browser-portable so the whole app can eventually
// run in a tab against a delegated token. It IS the I/O -- unlike the engine --
// but only over `fetch`, with the token and cache injected.
// packages/graph/src/purity.test.ts asserts the same thing at test time.
{
files: ["packages/graph/src/**/*.ts"],
rules: {
"no-restricted-imports": [
"error",
{
patterns: [
{
group: ["node:*", "fs", "path", "os", "crypto", "http", "https", "dns", "child_process"],
message:
"The Graph layer must stay browser-portable -- it uses fetch and AbortController only. Keep Node APIs in apps/server.",
},
{
group: ["@azure/*", "dotenv", "fastify", "@fastify/*"],
message:
"Server-only dependency. The Graph client takes an injected getToken; the server supplies the MSAL one.",
},
],
},
],
},
},
// Tests are allowed the Node APIs they need to inspect the source tree.
{
files: ["**/*.test.ts", "**/*.test.tsx"],
rules: { "no-restricted-imports": "off" },
}
);