From 244254167e5f1d9916bc956cd5ea8c74f2a65ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=9E=E5=8F=AF=20=C2=B7=20YU=20KE?= <1798456934@qq.com> Date: Mon, 31 Aug 2026 23:59:19 +0800 Subject: [PATCH] fix(eslint-config): disable unsafe catalog autofixes (#8341) * fix(eslint-config): disable unsafe catalog autofixes * test(eslint-config): cover non-mutating catalog lint --- .../eslint-config/src/configs/pnpm.test.ts | 70 +++++++++++++++++++ .../eslint-config/src/configs/pnpm.ts | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 internal/lint-configs/eslint-config/src/configs/pnpm.test.ts diff --git a/internal/lint-configs/eslint-config/src/configs/pnpm.test.ts b/internal/lint-configs/eslint-config/src/configs/pnpm.test.ts new file mode 100644 index 000000000..6b912977e --- /dev/null +++ b/internal/lint-configs/eslint-config/src/configs/pnpm.test.ts @@ -0,0 +1,70 @@ +import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +import { ESLint } from 'eslint'; +import { describe, expect, it } from 'vitest'; + +import { jsonc } from './jsonc'; +import { pnpm } from './pnpm'; + +describe('pnpm eslint config', () => { + it('reports invalid catalog entries without applying autofixes', async () => { + const [packageJsonConfig] = await pnpm(); + + expect(packageJsonConfig?.rules?.['pnpm/json-valid-catalog']).toEqual([ + 'error', + { autofix: false }, + ]); + }); + + it('does not change an invalid catalog during an ESLint autofix run', async () => { + const fixtureDirectory = await mkdtemp( + join(tmpdir(), 'vben-pnpm-catalog-'), + ); + const packageJsonPath = join(fixtureDirectory, 'package.json'); + const workspacePath = join(fixtureDirectory, 'pnpm-workspace.yaml'); + const packageJson = `${JSON.stringify( + { + name: 'catalog-fixture', + private: true, + dependencies: { + 'missing-catalog-package': 'catalog:missing', + }, + }, + null, + )}\n`; + const workspace = 'packages: []\ncatalog:\n existing-package: ^1.0.0\n'; + + try { + await writeFile(packageJsonPath, packageJson); + await writeFile(workspacePath, workspace); + + const eslint = new ESLint({ + cwd: fixtureDirectory, + fix: true, + overrideConfig: [...(await jsonc()), ...(await pnpm())], + overrideConfigFile: true, + }); + const [result] = await eslint.lintFiles(['package.json']); + + expect(result?.messages).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + ruleId: 'pnpm/json-valid-catalog', + }), + ]), + ); + expect(result?.output).toBeUndefined(); + + // The rule queues workspace writes asynchronously when autofixes are enabled. + await new Promise((resolve) => setTimeout(resolve, 1100)); + await expect(readFile(packageJsonPath, 'utf8')).resolves.toBe( + packageJson, + ); + await expect(readFile(workspacePath, 'utf8')).resolves.toBe(workspace); + } finally { + await rm(fixtureDirectory, { force: true, recursive: true }); + } + }); +}); diff --git a/internal/lint-configs/eslint-config/src/configs/pnpm.ts b/internal/lint-configs/eslint-config/src/configs/pnpm.ts index 5fe5afbf0..e2a45a874 100644 --- a/internal/lint-configs/eslint-config/src/configs/pnpm.ts +++ b/internal/lint-configs/eslint-config/src/configs/pnpm.ts @@ -18,7 +18,7 @@ export async function pnpm(): Promise { rules: { 'pnpm/json-enforce-catalog': 'error', 'pnpm/json-prefer-workspace-settings': 'error', - 'pnpm/json-valid-catalog': 'error', + 'pnpm/json-valid-catalog': ['error', { autofix: false }], }, }, {