chore: migrate ESLint Configuration to the new flat config format (#8482)

* chore: bump node-version to v18.18

min required version for eslint flat config

* chore: migrate eslint to flat config

* chore: migrate monorepo to flat config

* fix: remove old eslint unused disable directives

* chore: include meta-updater in the tsconfig

* style: remove semicolons

* style: fix

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
Paul Nodet
2024-09-01 23:06:12 +02:00
committed by GitHub
parent d500d9f12e
commit 86732affd0
16 changed files with 200 additions and 131 deletions

View File

@@ -1,2 +0,0 @@
fixtures
__fixtures__

View File

@@ -1,4 +0,0 @@
{
"root": true,
"extends": "@pnpm/eslint-config"
}

View File

@@ -4,10 +4,12 @@
"private": true,
"type": "module",
"scripts": {
"lint": "eslint \"src/**/*.ts\"",
"compile": "tsc --build"
},
"dependencies": {
"@pnpm/lockfile.fs": "workspace:*",
"@pnpm/meta-updater": "catalog:",
"@pnpm/types": "workspace:*",
"@types/normalize-path": "catalog:",
"is-subdir": "catalog:",

View File

@@ -11,9 +11,9 @@ import writeJsonFile from 'write-json-file'
const NEXT_TAG = 'next-9'
const CLI_PKG_NAME = 'pnpm'
export default async (workspaceDir: string) => {
const pnpmManifest = loadJsonFile.sync<any>(path.join(workspaceDir, 'pnpm/package.json'))
const pnpmVersion = pnpmManifest!['version'] // eslint-disable-line
export default async (workspaceDir: string) => { // eslint-disable-line
const pnpmManifest = loadJsonFile.sync<ProjectManifest>(path.join(workspaceDir, 'pnpm/package.json'))
const pnpmVersion = pnpmManifest!.version!
const pnpmMajorKeyword = `pnpm${pnpmVersion.split('.')[0]}`
const utilsDir = path.join(workspaceDir, '__utils__')
const lockfile = await readWantedLockfile(workspaceDir, { ignoreIncompatible: false })
@@ -21,9 +21,9 @@ export default async (workspaceDir: string) => {
throw new Error('no lockfile found')
}
return createUpdateOptions({
'package.json': (manifest: ProjectManifest & { keywords?: string[] } | null, { dir }) => {
'package.json': (manifest: ProjectManifest & { keywords?: string[] } | null, { dir }: { dir: string }) => {
if (!manifest) {
return manifest;
return manifest
}
if (manifest.name === 'monorepo-root') {
manifest.scripts!['release'] = `pnpm --filter=@pnpm/exe publish --tag=${NEXT_TAG} --access=public && pnpm publish --filter=!pnpm --filter=!@pnpm/exe --access=public && pnpm publish --filter=pnpm --tag=${NEXT_TAG} --access=public`
@@ -32,12 +32,12 @@ export default async (workspaceDir: string) => {
if (manifest.name && manifest.name !== CLI_PKG_NAME) {
manifest.devDependencies = {
...manifest.devDependencies,
[manifest.name]: `workspace:*`,
[manifest.name]: 'workspace:*',
}
} else if (manifest.name === CLI_PKG_NAME && manifest.devDependencies) {
delete manifest.devDependencies[manifest.name]
}
if (manifest.private || isSubdir(utilsDir, dir)) return manifest
if (manifest.private === true || isSubdir(utilsDir, dir)) return manifest
manifest.keywords = [
pnpmMajorKeyword,
...(manifest.keywords ?? []).filter((keyword) => !/^pnpm[0-9]+$/.test(keyword)),
@@ -73,7 +73,7 @@ export default async (workspaceDir: string) => {
manifest.version = pnpmVersion
if (manifest.name === '@pnpm/exe') {
for (const depName of ['@pnpm/linux-arm64', '@pnpm/linux-x64', '@pnpm/win-x64', '@pnpm/win-arm64', '@pnpm/macos-x64', '@pnpm/macos-arm64']) {
manifest.optionalDependencies![depName] = `workspace:*`
manifest.optionalDependencies![depName] = 'workspace:*'
}
}
return manifest
@@ -84,9 +84,9 @@ export default async (workspaceDir: string) => {
lockfile,
workspaceDir,
}),
'cspell.json': (cspell: any) => {
if (cspell?.words) {
cspell.words = cspell.words.sort()
'cspell.json': (cspell: any) => { // eslint-disable-line
if (cspell && typeof cspell === 'object' && 'words' in cspell && Array.isArray(cspell.words)) {
cspell.words = cspell.words.sort((w1: string, w2: string) => w1.localeCompare(w2))
}
return cspell
},
@@ -147,13 +147,13 @@ async function updateTSConfig (
compilerOptions: {
noEmit: false,
outDir: '../test.lib',
rootDir: '.'
rootDir: '.',
},
include: [
'**/*.ts',
normalizePath(path.relative(testDir, path.join(context.workspaceDir, '__typings__/**/*.d.ts'))),
],
references: (tsConfig as any)?.compilerOptions?.composite === false
references: (tsConfig as any)?.compilerOptions?.composite === false // eslint-disable-line
// If composite is explicitly set to false, we can't add the main
// tsconfig.json as a project reference. Only composite enabled projects
// can be referenced by definition. Instead, we have to add all the
@@ -168,7 +168,7 @@ async function updateTSConfig (
// methods to be defensive against future changes to testDir, dir, or
// relPath.
? linkValues.map(relPath => ({
path: normalizePath(path.relative(testDir, path.join(dir, relPath)))
path: normalizePath(path.relative(testDir, path.join(dir, relPath))),
}))
// If the main project is composite (the more common case), we can
@@ -178,7 +178,7 @@ async function updateTSConfig (
// The project reference allows editor features like Go to Definition
// jump to files in src for imports using the current package's name
// (ex: @pnpm/config).
: [{ path: ".." }]
: [{ path: '..' }],
}, { indent: 2 })
}
@@ -191,13 +191,13 @@ async function updateTSConfig (
'test/**/*.ts',
normalizePath(path.relative(dir, path.join(context.workspaceDir, '__typings__/**/*.d.ts'))),
],
}, { indent: 2 })
}, { indent: 2 }),
])
return {
...tsConfig,
extends: '@pnpm/tsconfig',
compilerOptions: {
...(tsConfig as any)['compilerOptions'],
...(tsConfig as any)['compilerOptions'], // eslint-disable-line
rootDir: 'src',
},
references: linkValues.map(path => ({ path })),

2
.npmrc
View File

@@ -5,7 +5,7 @@ hoist-pattern[] = jest-runner
shared-workspace-lockfile = true
publish-branch = main
pnpmfile = .pnpmfile.cjs
node-version = 18.12.0
node-version = 18.18.0
engine-strict = true
save-prefix=
; dedupe-direct-deps=true ; Otherwise exporting the manifest fails sometimes

View File

@@ -1,100 +0,0 @@
{
"extends": ["standard-with-typescript"],
"parserOptions": {
"project": "./tsconfig.lint.json",
"sourceType": "module"
},
"reportUnusedDisableDirectives": true,
"rules": {
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": [
"**/pnpm/src/**",
"**/test/**",
"**/src/**/*.test.ts"
]
}
],
"import/no-default-export": "error",
"@typescript-eslint/indent": [
"error",
2,
{
"FunctionDeclaration": {
"parameters": "first"
},
"FunctionExpression": {
"parameters": "first"
}
}
],
"@typescript-eslint/consistent-indexed-object-style": "off",
"@typescript-eslint/prefer-reduce-type-parameter": "off",
"@typescript-eslint/naming-convention": "error",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "error",
"no-return-await": "error",
"no-await-in-loop": "error",
"@typescript-eslint/return-await": "off",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-use-before-define": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true
}
],
"@typescript-eslint/triple-slash-reference": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/consistent-type-assertions": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-base-to-string": "off",
"@typescript-eslint/no-dynamic-delete": "off",
"@typescript-eslint/promise-function-async": "off",
"@typescript-eslint/no-misused-promises": "off",
"no-multi-str": "off",
"no-mixed-operators": "off",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/explicit-module-boundary-types": "error",
"brace-style": [
"error",
"1tbs"
],
"@typescript-eslint/comma-dangle": [
"error",
{
"arrays": "always-multiline",
"exports": "always-multiline",
"functions": "never",
"imports": "always-multiline",
"objects": "always-multiline"
}
],
"curly": "off",
"eol-last": "off",
"import/order": "off",
"max-len": "off",
"no-multiple-empty-lines": "error",
"no-redeclare": "error",
"no-restricted-properties": [
"error",
{
"property": "substr",
"message": "Use .slice instead of .substr."
}
],
"no-trailing-spaces": "error",
"no-var": "error",
"space-before-function-paren": [
"error",
"always"
]
}
}

View File

@@ -1 +1,106 @@
module.exports = require('./eslint.json')
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import js from '@eslint/js'
import { FlatCompat } from '@eslint/eslintrc'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
})
export default [...compat.extends('standard-with-typescript'), {
files: ['**/*.ts'],
linterOptions: {
reportUnusedDisableDirectives: true,
},
languageOptions: {
ecmaVersion: 5,
sourceType: 'module',
parserOptions: {
project: './tsconfig.lint.json',
},
},
rules: {
'import/no-extraneous-dependencies': ['error', {
devDependencies: ['**/pnpm/src/**', '**/test/**', '**/src/**/*.test.ts'],
}],
'import/no-default-export': 'error',
'@typescript-eslint/indent': ['error', 2, {
FunctionDeclaration: {
parameters: 'first',
},
FunctionExpression: {
parameters: 'first',
},
}],
'@typescript-eslint/consistent-indexed-object-style': 'off',
'@typescript-eslint/prefer-reduce-type-parameter': 'off',
'@typescript-eslint/naming-convention': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'error',
'no-return-await': 'error',
'no-await-in-loop': 'error',
'@typescript-eslint/return-await': 'off',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-use-before-define': 'error',
'@typescript-eslint/no-var-requires': 'error',
'@typescript-eslint/quotes': ['error', 'single', {
avoidEscape: true,
}],
'@typescript-eslint/triple-slash-reference': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/consistent-type-assertions': 'off',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-dynamic-delete': 'off',
'@typescript-eslint/promise-function-async': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'no-multi-str': 'off',
'no-mixed-operators': 'off',
'@typescript-eslint/dot-notation': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'error',
'brace-style': ['error', '1tbs'],
'@typescript-eslint/comma-dangle': ['error', {
arrays: 'always-multiline',
exports: 'always-multiline',
functions: 'never',
imports: 'always-multiline',
objects: 'always-multiline',
}],
curly: 'off',
'eol-last': 'off',
'import/order': 'off',
'max-len': 'off',
'no-multiple-empty-lines': 'error',
'no-redeclare': 'error',
'no-restricted-properties': ['error', {
property: 'substr',
message: 'Use .slice instead of .substr.',
}],
'no-trailing-spaces': 'error',
'no-var': 'error',
'no-lone-blocks': 'off',
'space-before-function-paren': ['error', 'always'],
},
}]

View File

@@ -10,6 +10,7 @@
"bugs": {
"url": "https://github.com/pnpm/eslint-config/issues"
},
"type": "module",
"main": "index.js",
"directories": {
"test": "test"
@@ -23,6 +24,8 @@
"repository": "https://github.com/pnpm/pnpm/blob/master/utils/eslint-config",
"scripts": {},
"dependencies": {
"@eslint/eslintrc": "3.1.0",
"@eslint/js": "9.9.1",
"@typescript-eslint/eslint-plugin": "6.18.1",
"@typescript-eslint/parser": "6.18.1",
"eslint": "^8.57.0",

View File

@@ -15,7 +15,6 @@ describe('TestEchoServer', () => {
it('cleans up through Symbol.asyncDispose', async () => {
let listenPath: string
// eslint-disable-next-line no-lone-blocks
{
await using server = await createTestIpcServer()
listenPath = server.listenPath

View File

@@ -1,6 +1,5 @@
{
"words": [
"TLSV",
"adduser",
"adipiscing",
"amet",
@@ -248,6 +247,7 @@
"teambit",
"tempy",
"testcase",
"TLSV",
"todomvc",
"tsparticles",
"typecheck",

5
eslint.config.mjs Normal file
View File

@@ -0,0 +1,5 @@
import eslintConfig from "@pnpm/eslint-config";
export default [{
ignores: ["**/fixtures", "**/__fixtures__"],
}, ...eslintConfig];

View File

@@ -1,7 +1,7 @@
import { promisify } from 'util'
import gfs from 'graceful-fs'
export default { // eslint-disable-line
export default {
copyFile: promisify(gfs.copyFile),
copyFileSync: gfs.copyFileSync,
createReadStream: gfs.createReadStream,

View File

@@ -39,7 +39,7 @@
"@commitlint/config-conventional": "^17.8.1",
"@commitlint/prompt-cli": "^17.8.1",
"@pnpm/eslint-config": "workspace:*",
"@pnpm/meta-updater": "2.0.3",
"@pnpm/meta-updater": "catalog:",
"@pnpm/registry-mock": "catalog:",
"@pnpm/tsconfig": "workspace:*",
"@pnpm/worker": "workspace:*",

63
pnpm-lock.yaml generated
View File

@@ -30,6 +30,9 @@ catalogs:
'@pnpm/log.group':
specifier: 3.0.0
version: 3.0.0
'@pnpm/meta-updater':
specifier: 2.0.3
version: 2.0.3
'@pnpm/network.agent':
specifier: ^2.0.0
version: 2.0.0
@@ -711,7 +714,7 @@ importers:
specifier: workspace:*
version: link:__utils__/eslint-config
'@pnpm/meta-updater':
specifier: 2.0.3
specifier: 'catalog:'
version: 2.0.3
'@pnpm/registry-mock':
specifier: 'catalog:'
@@ -782,6 +785,9 @@ importers:
'@pnpm/lockfile.fs':
specifier: workspace:*
version: link:../lockfile/fs
'@pnpm/meta-updater':
specifier: 'catalog:'
version: 2.0.3
'@pnpm/types':
specifier: workspace:*
version: link:../packages/types
@@ -881,6 +887,12 @@ importers:
__utils__/eslint-config:
dependencies:
'@eslint/eslintrc':
specifier: 3.1.0
version: 3.1.0
'@eslint/js':
specifier: 9.9.1
version: 9.9.1
'@typescript-eslint/eslint-plugin':
specifier: 6.18.1
version: 6.18.1(@typescript-eslint/parser@6.18.1(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)
@@ -8324,10 +8336,18 @@ packages:
resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
'@eslint/eslintrc@3.1.0':
resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@8.57.0':
resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
'@eslint/js@9.9.1':
resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@gwhitney/detect-indent@7.0.1':
resolution: {integrity: sha512-7bQW+gkKa2kKZPeJf6+c6gFK9ARxQfn+FKy9ScTBppyKRWH2KzsmweXUoklqeEiHiNVWaeP5csIdsNq6w7QhzA==}
engines: {node: '>=12.20'}
@@ -10503,6 +10523,10 @@ packages:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
eslint-visitor-keys@4.0.0:
resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint@8.57.0:
resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -10512,6 +10536,10 @@ packages:
resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==}
engines: {node: '>=6'}
espree@10.1.0:
resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -10945,6 +10973,10 @@ packages:
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
engines: {node: '>=8'}
globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
globalthis@1.0.4:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
@@ -13739,6 +13771,7 @@ packages:
uid-number@0.0.6:
resolution: {integrity: sha512-c461FXIljswCuscZn67xq9PpszkPT6RjheWFQTgCyabJrTUozElanb0YEqv2UGgk247YpcJkFBuSGNvBlpXM9w==}
deprecated: This package is no longer supported.
umask@1.1.0:
resolution: {integrity: sha512-lE/rxOhmiScJu9L6RTNVgB/zZbF+vGC0/p6D3xnkAePI2o0sMyFG966iR5Ki50OI/0mNi2yaRnxfLsPmEZF/JA==}
@@ -15000,8 +15033,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@eslint/eslintrc@3.1.0':
dependencies:
ajv: 6.12.6
debug: 4.3.6
espree: 10.1.0
globals: 14.0.0
ignore: 5.3.2
import-fresh: 3.3.0
js-yaml: '@zkochan/js-yaml@0.0.7'
minimatch: 3.1.2
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
'@eslint/js@8.57.0': {}
'@eslint/js@9.9.1': {}
'@gwhitney/detect-indent@7.0.1': {}
'@humanwhocodes/config-array@0.11.14':
@@ -15262,7 +15311,7 @@ snapshots:
'@npmcli/fs@3.1.1':
dependencies:
semver: 7.6.2
semver: 7.6.3
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -17794,6 +17843,8 @@ snapshots:
eslint-visitor-keys@3.4.3: {}
eslint-visitor-keys@4.0.0: {}
eslint@8.57.0:
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
@@ -17839,6 +17890,12 @@ snapshots:
esm@3.2.25: {}
espree@10.1.0:
dependencies:
acorn: 8.12.1
acorn-jsx: 5.3.2(acorn@8.12.1)
eslint-visitor-keys: 4.0.0
espree@9.6.1:
dependencies:
acorn: 8.12.1
@@ -18348,6 +18405,8 @@ snapshots:
dependencies:
type-fest: 0.20.2
globals@14.0.0: {}
globalthis@1.0.4:
dependencies:
define-properties: 1.2.1

View File

@@ -45,6 +45,7 @@ catalog:
"@pnpm/exec": ^2.0.0
"@pnpm/fs.packlist": 2.0.0
"@pnpm/log.group": 3.0.0
"@pnpm/meta-updater": 2.0.3
"@pnpm/network.agent": ^2.0.0
"@pnpm/nopt": ^0.2.1
"@pnpm/npm-conf": 2.3.1

View File

@@ -5,6 +5,7 @@
"rootDir": "src"
},
"include": [
".meta-updater/**/*.ts",
"**/src/**/*.ts",
"**/test/**/*.ts",
"typings/**/*.d.ts"