Centralize ESLint into a single root config

Replace the duplicated per-workspace eslint.config.mjs files in
apps/console, apps/trust, packages/ui, and packages/eslint-config with
one root eslint.config.mjs that reuses the shared @probo/eslint-config
rule sets and scopes them per directory. Linting now runs from the repo
root, so pin the type-checked project service root and broaden the
import-x resolver to every workspace tsconfig (the #/* aliases live in
each app's tsconfig.app.json).

Drop the now-redundant per-package lint scripts and lint-only devDeps,
and add a root lint script that runs eslint over the four dirs with
multithreading restored via --concurrency auto, then lints n8n-node
through a direct workspace call. packages/n8n-node keeps its own
external preset.

Collapse the redundant lint-js -> npm-lint Makefile chain into a single
lint-js target and update the make docs accordingly.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-19 16:36:09 +02:00
parent 652be7a984
commit 4d28dab2f4
14 changed files with 339 additions and 927 deletions

View File

@@ -107,16 +107,13 @@ lint: lint-go lint-js
lint-go: vet go-fmt go-fix go-lint
.PHONY: lint-js
lint-js: npm-lint
lint-js:
$(NPM) run lint
.PHONY: vet
vet: generate embed
$(GO_VET) ./...
.PHONY: npm-lint
npm-lint:
$(NPM) run lint
.PHONY: go-fmt
go-fmt:
@output="$$(gofmt -l apps cmd packages pkg e2e)"; \

View File

@@ -1,12 +0,0 @@
import { configs } from "@probo/eslint-config";
import { defineConfig } from "eslint/config";
export default defineConfig([
configs.base,
configs.ts,
configs.imports,
configs.react,
configs.relay,
configs.stylistic,
configs.languageOptions.browser,
]);

View File

@@ -6,7 +6,6 @@
"scripts": {
"dev": "vite --port 5173",
"build": "tsc -b && vite build",
"lint": "eslint . --concurrency 4",
"check": "tsc --noEmit -p tsconfig.app.json",
"preview": "vite preview"
},
@@ -38,7 +37,6 @@
},
"devDependencies": {
"@babel/core": "^7.29.0",
"@probo/eslint-config": "1.0.0",
"@probo/eslint-plugin-relay-types": "^1.0.0",
"@rolldown/plugin-babel": "^0.2.3",
"@tailwindcss/vite": "^4.3.1",
@@ -48,7 +46,6 @@
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"babel-plugin-relay": "^21.0.1",
"eslint": "^10.5.0",
"graphql": "^17.0.1",
"tailwindcss": "^4.3.1",
"typescript": "~6.0.3",

View File

@@ -1,12 +0,0 @@
import { configs } from "@probo/eslint-config";
import { defineConfig } from "eslint/config";
export default defineConfig([
configs.base,
configs.ts,
configs.imports,
configs.react,
configs.relay,
configs.stylistic,
configs.languageOptions.browser,
]);

View File

@@ -6,7 +6,6 @@
"scripts": {
"dev": "vite --port 5174",
"build": "tsc -b && vite build",
"lint": "eslint . --concurrency 2",
"check": "tsc --noEmit -p tsconfig.app.json",
"preview": "vite preview"
},
@@ -31,7 +30,6 @@
},
"devDependencies": {
"@babel/core": "^7.29.0",
"@probo/eslint-config": "1.0.0",
"@probo/eslint-plugin-relay-types": "^1.0.0",
"@rolldown/plugin-babel": "^0.2.3",
"@tailwindcss/vite": "^4.3.1",
@@ -41,7 +39,6 @@
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"babel-plugin-relay": "^21.0.1",
"eslint": "^10.5.0",
"graphql": "^17.0.1",
"tailwindcss": "^4.3.1",
"typescript": "~6.0.3",

View File

@@ -14,7 +14,7 @@ The project uses a `GNUmakefile` at the root. Builds run with `--jobs=$(nproc)`
| `make test-short` | Short tests only |
| `make test-bench` | Run benchmarks |
| `make test-e2e` | Run console end-to-end tests (requires `bin/probod`) |
| `make lint` | Run all linters: `vet` + `go-fmt` + `go-fix` + `go-lint` + `npm-lint` |
| `make lint` | Run all linters: `vet` + `go-fmt` + `go-fix` + `go-lint` + `lint-js` |
| `make fmt` | Format Go code (`go fmt ./...`) |
| `make clean` | Remove all build artifacts, `node_modules`, generated files, and coverage |
| `make help` | List targets with `##` doc comments |

66
eslint.config.mjs Normal file
View File

@@ -0,0 +1,66 @@
import { configs } from "@probo/eslint-config";
import { defineConfig, globalIgnores } from "eslint/config";
// Workspaces that are linted by this root config. Each gets the shared rule
// sets below; everything else is ignored so a bare `eslint .` keeps the same
// scope as the previous per-workspace configs.
const appDirs = ["apps/console/**", "apps/trust/**"];
const reactDirs = [...appDirs, "packages/ui/**"];
const lintedDirs = [...reactDirs, "packages/eslint-config/**"];
export default defineConfig([
// Keep `configs.base` global so its `globalIgnores` (dist, __generated__,
// *.d.ts, ...) stay global rather than being scoped by a wrapping `files`.
configs.base,
globalIgnores([
"examples/**",
"packages/coredata/**",
"packages/cookie-banner/**",
"packages/emails/**",
"packages/eslint-relay-plugin-types/**",
"packages/helpers/**",
"packages/hooks/**",
"packages/i18n/**",
"packages/n8n-node/**",
"packages/prosemirror/**",
"packages/react-lazy/**",
"packages/relay/**",
"packages/routes/**",
"packages/tsconfig/**",
]),
{
files: lintedDirs,
extends: [configs.ts, configs.imports, configs.stylistic],
// Linting runs from the repo root, so pin the project service root and let
// it resolve each file to its nearest package tsconfig.json.
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
},
},
{
files: reactDirs,
extends: [configs.react],
},
{
files: appDirs,
extends: [configs.relay],
},
{
files: reactDirs,
ignores: ["packages/ui/tailwind.config.js"],
extends: [configs.languageOptions.browser],
},
{
files: ["packages/eslint-config/**"],
extends: [configs.languageOptions.node],
},
{
files: ["packages/ui/tailwind.config.js"],
extends: [configs.languageOptions.node],
languageOptions: {
sourceType: "commonjs",
},
},
]);

1107
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,11 +13,13 @@
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"lint": "eslint apps/console apps/trust packages/ui packages/eslint-config --concurrency auto && npm -w @probo/n8n-nodes-probo run lint",
"check": "turbo run check",
"relay": "relay-compiler"
},
"devDependencies": {
"@probo/eslint-config": "1.0.0",
"eslint": "^10.5.0",
"relay-compiler": "^21.0.1",
"turbo": "^2.9.14"
},

View File

@@ -1,15 +0,0 @@
import { defineConfig } from "eslint/config";
import { baseConfigs } from "#baseConfigs";
import { importsConfigs } from "#importsConfigs";
import { nodeLanguageOptionsConfigs } from "#languageOptionsConfigs";
import { stylisticConfigs } from "#stylisticConfigs";
import { tsConfigs } from "#tsConfigs";
export default defineConfig([
...baseConfigs,
...tsConfigs,
...importsConfigs,
...stylisticConfigs,
...nodeLanguageOptionsConfigs,
]);

View File

@@ -19,9 +19,7 @@
"#languageOptionsConfigs": "./src/languageOptionsConfigs.ts",
"#stylisticConfigs": "./src/stylisticConfigs.ts"
},
"scripts": {
"lint": "eslint src"
},
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",

View File

@@ -47,7 +47,12 @@ export const importsConfigs: FlatConfig.ConfigArray = [
settings: {
"import-x/resolver-next": createTypeScriptImportResolver({
alwaysTryTypes: true,
project: "tsconfig.json",
// Linting runs from the repo root, so resolve every workspace's
// tsconfig rather than a single cwd-relative one. The `#/*` path
// aliases live in the per-app `tsconfig.app.json`, so match all
// tsconfig variants, not just the references-only `tsconfig.json`.
project: ["apps/*/tsconfig*.json", "packages/*/tsconfig*.json"],
noWarnOnMultipleProjects: true,
}),
},
},

View File

@@ -1,21 +0,0 @@
import { configs } from "@probo/eslint-config";
import { defineConfig } from "eslint/config";
export default defineConfig([
configs.base,
configs.ts,
configs.imports,
configs.react,
configs.stylistic,
{
extends: [configs.languageOptions.browser],
ignores: ["./tailwind.config.js"],
},
{
extends: [configs.languageOptions.node],
files: ["./tailwind.config.js"],
languageOptions: {
sourceType: "commonjs",
},
},
]);

View File

@@ -6,7 +6,6 @@
"sideEffects": false,
"main": "src/index.ts",
"scripts": {
"lint": "eslint . --concurrency 2",
"dev": "storybook dev -p 6006 --no-open",
"check": "tsc --noEmit -p tsconfig.app.json",
"icons": "bun run src/Atoms/Icons/generator.ts"
@@ -48,7 +47,6 @@
},
"devDependencies": {
"@chromatic-com/storybook": "^5.0.1",
"@probo/eslint-config": "1.0.0",
"@rollup/pluginutils": "^5.1.4",
"@storybook/addon-vitest": "^10.2.8",
"@storybook/react": "^10.2.8",
@@ -60,7 +58,6 @@
"@vitejs/plugin-react": "^6.0.2",
"@vitest/browser": "4.1.8",
"@vitest/coverage-v8": "4.1.8",
"eslint": "^10.5.0",
"playwright": "^1.55.1",
"react": "^19.2.7",
"react-docgen": "^7.1.1",