From 9a2343f29ecf23f7783a147a2e83d17c452dbf72 Mon Sep 17 00:00:00 2001 From: Louis Orleans Date: Tue, 7 May 2024 23:50:52 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=E2=99=BB=EF=B8=8F=20use=20rushstac?= =?UTF-8?q?k's=20eslint-patch=20to=20avoid=20eslint=20dep=20hoist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also refactors all configs that use plugins to be written in TS instead of YAML --- code-style.code-workspace | 7 - package-lock.json | 121 ++++------------- packages/eslint-config-esmodule/base.yaml | 12 -- packages/eslint-config-esmodule/package.json | 16 ++- packages/eslint-config-esmodule/src/base.ts | 21 +++ .../tsconfig.build.json | 8 ++ packages/eslint-config-esmodule/tsconfig.json | 14 ++ packages/eslint-config-jest/base.yaml | 29 ---- packages/eslint-config-jest/lenient.yaml | 15 --- packages/eslint-config-jest/package.json | 19 +-- packages/eslint-config-jest/src/base.ts | 42 ++++++ packages/eslint-config-jest/src/lenient.ts | 20 +++ packages/eslint-config-jest/src/utils.ts | 8 ++ .../eslint-config-jest/tsconfig.build.json | 8 ++ packages/eslint-config-jest/tsconfig.json | 14 ++ packages/eslint-config-nextjs/base.yaml | 6 - packages/eslint-config-nextjs/package.json | 18 ++- packages/eslint-config-nextjs/src/base.ts | 12 ++ .../eslint-config-nextjs/tsconfig.build.json | 8 ++ packages/eslint-config-nextjs/tsconfig.json | 14 ++ packages/eslint-config-node/base.yaml | 103 --------------- packages/eslint-config-node/lenient.yaml | 10 -- packages/eslint-config-node/package.json | 20 +-- packages/eslint-config-node/src/base.ts | 125 ++++++++++++++++++ packages/eslint-config-node/src/lenient.ts | 17 +++ .../eslint-config-node/tsconfig.build.json | 8 ++ packages/eslint-config-node/tsconfig.json | 14 +- packages/eslint-config-react/base.yaml | 26 ---- packages/eslint-config-react/package.json | 16 ++- packages/eslint-config-react/src/base.ts | 35 +++++ .../eslint-config-react/tsconfig.build.json | 8 ++ packages/eslint-config-react/tsconfig.json | 14 ++ packages/eslint-config-typescript/base.yaml | 102 -------------- .../eslint-config-typescript/lenient.yaml | 39 ------ .../eslint-config-typescript/package.json | 18 +-- packages/eslint-config-typescript/src/base.ts | 120 +++++++++++++++++ .../eslint-config-typescript/src/lenient.ts | 51 +++++++ .../tsconfig.build.json | 8 ++ .../eslint-config-typescript/tsconfig.json | 13 +- packages/eslint-config/base.yaml | 29 ---- packages/eslint-config/lenient.yaml | 47 ------- packages/eslint-config/overrides/index.yaml | 12 -- packages/eslint-config/overrides/json.yaml | 6 - packages/eslint-config/overrides/testing.yaml | 31 ----- packages/eslint-config/package.json | 28 ++-- packages/eslint-config/rule-sets/bugs.yaml | 21 --- .../eslint-config/rule-sets/deprecated.yaml | 9 -- .../eslint-config/rule-sets/footguns.yaml | 68 ---------- packages/eslint-config/rule-sets/imports.yaml | 63 --------- .../rule-sets/miscellaneous.yaml | 17 --- .../eslint-config/rule-sets/modern-code.yaml | 15 --- .../eslint-config/rule-sets/promises.yaml | 21 --- .../eslint-config/rule-sets/readability.yaml | 24 ---- .../eslint-config/rule-sets/security.yaml | 4 - packages/eslint-config/src/base.ts | 33 +++++ packages/eslint-config/src/lenient.ts | 27 ++++ packages/eslint-config/src/overrides/index.ts | 23 ++++ packages/eslint-config/src/overrides/json.ts | 10 ++ .../eslint-config/src/overrides/testing.ts | 40 ++++++ packages/eslint-config/src/rule-sets/bugs.ts | 32 +++++ .../eslint-config/src/rule-sets/deprecated.ts | 16 +++ .../eslint-config/src/rule-sets/footguns.ts | 77 +++++++++++ .../eslint-config/src/rule-sets/imports.ts | 86 ++++++++++++ .../src/rule-sets/miscellaneous.ts | 26 ++++ .../src/rule-sets/modern-code.ts | 22 +++ .../eslint-config/src/rule-sets/promises.ts | 28 ++++ .../src/rule-sets/readability.ts | 49 +++++++ .../eslint-config/src/rule-sets/security.ts | 11 ++ packages/eslint-config/tsconfig.build.json | 8 ++ packages/eslint-config/tsconfig.json | 14 ++ .../package.json | 30 ----- .../package.json | 35 ----- .../package.json | 30 ----- .../package.json | 35 ----- .../package.json | 37 ------ .../package.json | 37 ------ .../eslint-npm-hoist-packages/package.json | 40 ------ 77 files changed, 1178 insertions(+), 1122 deletions(-) delete mode 100644 packages/eslint-config-esmodule/base.yaml create mode 100644 packages/eslint-config-esmodule/src/base.ts create mode 100644 packages/eslint-config-esmodule/tsconfig.build.json create mode 100644 packages/eslint-config-esmodule/tsconfig.json delete mode 100644 packages/eslint-config-jest/base.yaml delete mode 100644 packages/eslint-config-jest/lenient.yaml create mode 100644 packages/eslint-config-jest/src/base.ts create mode 100644 packages/eslint-config-jest/src/lenient.ts create mode 100644 packages/eslint-config-jest/src/utils.ts create mode 100644 packages/eslint-config-jest/tsconfig.build.json create mode 100644 packages/eslint-config-jest/tsconfig.json delete mode 100644 packages/eslint-config-nextjs/base.yaml create mode 100644 packages/eslint-config-nextjs/src/base.ts create mode 100644 packages/eslint-config-nextjs/tsconfig.build.json create mode 100644 packages/eslint-config-nextjs/tsconfig.json delete mode 100644 packages/eslint-config-node/base.yaml delete mode 100644 packages/eslint-config-node/lenient.yaml create mode 100644 packages/eslint-config-node/src/base.ts create mode 100644 packages/eslint-config-node/src/lenient.ts create mode 100644 packages/eslint-config-node/tsconfig.build.json delete mode 100644 packages/eslint-config-react/base.yaml create mode 100644 packages/eslint-config-react/src/base.ts create mode 100644 packages/eslint-config-react/tsconfig.build.json create mode 100644 packages/eslint-config-react/tsconfig.json delete mode 100644 packages/eslint-config-typescript/base.yaml delete mode 100644 packages/eslint-config-typescript/lenient.yaml create mode 100644 packages/eslint-config-typescript/src/base.ts create mode 100644 packages/eslint-config-typescript/src/lenient.ts create mode 100644 packages/eslint-config-typescript/tsconfig.build.json delete mode 100644 packages/eslint-config/base.yaml delete mode 100644 packages/eslint-config/lenient.yaml delete mode 100644 packages/eslint-config/overrides/index.yaml delete mode 100644 packages/eslint-config/overrides/json.yaml delete mode 100644 packages/eslint-config/overrides/testing.yaml delete mode 100644 packages/eslint-config/rule-sets/bugs.yaml delete mode 100644 packages/eslint-config/rule-sets/deprecated.yaml delete mode 100644 packages/eslint-config/rule-sets/footguns.yaml delete mode 100644 packages/eslint-config/rule-sets/imports.yaml delete mode 100644 packages/eslint-config/rule-sets/miscellaneous.yaml delete mode 100644 packages/eslint-config/rule-sets/modern-code.yaml delete mode 100644 packages/eslint-config/rule-sets/promises.yaml delete mode 100644 packages/eslint-config/rule-sets/readability.yaml delete mode 100644 packages/eslint-config/rule-sets/security.yaml create mode 100644 packages/eslint-config/src/base.ts create mode 100644 packages/eslint-config/src/lenient.ts create mode 100644 packages/eslint-config/src/overrides/index.ts create mode 100644 packages/eslint-config/src/overrides/json.ts create mode 100644 packages/eslint-config/src/overrides/testing.ts create mode 100644 packages/eslint-config/src/rule-sets/bugs.ts create mode 100644 packages/eslint-config/src/rule-sets/deprecated.ts create mode 100644 packages/eslint-config/src/rule-sets/footguns.ts create mode 100644 packages/eslint-config/src/rule-sets/imports.ts create mode 100644 packages/eslint-config/src/rule-sets/miscellaneous.ts create mode 100644 packages/eslint-config/src/rule-sets/modern-code.ts create mode 100644 packages/eslint-config/src/rule-sets/promises.ts create mode 100644 packages/eslint-config/src/rule-sets/readability.ts create mode 100644 packages/eslint-config/src/rule-sets/security.ts create mode 100644 packages/eslint-config/tsconfig.build.json create mode 100644 packages/eslint-config/tsconfig.json delete mode 100644 packages/eslint-npm-hoist-packages-esmodule/package.json delete mode 100644 packages/eslint-npm-hoist-packages-jest/package.json delete mode 100644 packages/eslint-npm-hoist-packages-nextjs/package.json delete mode 100644 packages/eslint-npm-hoist-packages-node/package.json delete mode 100644 packages/eslint-npm-hoist-packages-react/package.json delete mode 100644 packages/eslint-npm-hoist-packages-typescript/package.json delete mode 100644 packages/eslint-npm-hoist-packages/package.json diff --git a/code-style.code-workspace b/code-style.code-workspace index 033c31e2..a85b821b 100644 --- a/code-style.code-workspace +++ b/code-style.code-workspace @@ -17,13 +17,6 @@ { "path": "packages/eslint-config-node" }, { "path": "packages/eslint-config-react" }, { "path": "packages/eslint-config-typescript" }, - { "path": "packages/eslint-npm-hoist-packages" }, - { "path": "packages/eslint-npm-hoist-packages-esmodule" }, - { "path": "packages/eslint-npm-hoist-packages-jest" }, - { "path": "packages/eslint-npm-hoist-packages-nextjs" }, - { "path": "packages/eslint-npm-hoist-packages-node" }, - { "path": "packages/eslint-npm-hoist-packages-react" }, - { "path": "packages/eslint-npm-hoist-packages-typescript" }, { "path": "packages/eslint-plugin-nest" }, { "path": "packages/jest-configs" }, { "path": "packages/rubocop-configs" }, diff --git a/package-lock.json b/package-lock.json index 853973a0..15b76f3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -645,34 +645,6 @@ "resolved": "packages/eslint-config-typescript", "link": true }, - "node_modules/@code-style/eslint-npm-hoist-packages": { - "resolved": "packages/eslint-npm-hoist-packages", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-esmodule": { - "resolved": "packages/eslint-npm-hoist-packages-esmodule", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-jest": { - "resolved": "packages/eslint-npm-hoist-packages-jest", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-nextjs": { - "resolved": "packages/eslint-npm-hoist-packages-nextjs", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-node": { - "resolved": "packages/eslint-npm-hoist-packages-node", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-react": { - "resolved": "packages/eslint-npm-hoist-packages-react", - "link": true - }, - "node_modules/@code-style/eslint-npm-hoist-packages-typescript": { - "resolved": "packages/eslint-npm-hoist-packages-typescript", - "link": true - }, "node_modules/@code-style/eslint-plugin-nest": { "resolved": "packages/eslint-plugin-nest", "link": true @@ -2110,6 +2082,11 @@ "prettier": "^3.0.0" } }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz", + "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2215,9 +2192,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.56.9", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz", - "integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==", + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "devOptional": true, "dependencies": { "@types/estree": "*", @@ -10425,6 +10402,7 @@ "license": "MIT", "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.1.0", + "@rushstack/eslint-patch": "^1.10.2", "eslint": "^8.49.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", @@ -10441,7 +10419,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages": "2.0.0-30", "prettier": "^3.1.0" } }, @@ -10480,6 +10457,7 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-import": "^2.28.1" }, "devDependencies": { @@ -10491,7 +10469,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-esmodule": "2.0.0-30", "eslint": "^8.49.0" } }, @@ -10500,6 +10477,7 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-jest": "^27.4.0" }, "devDependencies": { @@ -10509,7 +10487,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-jest": "2.0.0-30", "eslint": "^8.49.0", "jest": "*" } @@ -10538,7 +10515,8 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "^14.1.1" + "@next/eslint-plugin-next": "^14.1.1", + "@rushstack/eslint-patch": "^1.10.2" }, "devDependencies": { "@types/react": "^18.2.23", @@ -10549,7 +10527,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-react": "2.0.0-30", "eslint": "^8.49.0", "next": "*" } @@ -10559,10 +10536,11 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-n": "^17.4.0" }, "devDependencies": { - "@types/eslint": "^8.44.2", + "@types/eslint": "^8.56.10", "@types/node": "^20.6.3", "tsm": "^2.3.0" }, @@ -10570,7 +10548,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-node": "2.0.0-30", "eslint": "^8.49.0" } }, @@ -10636,6 +10613,7 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0" @@ -10649,7 +10627,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-react": "2.0.0-30", "eslint": "^8.49.0", "react": ">=16.8", "react-dom": ">=16.8" @@ -10660,6 +10637,7 @@ "version": "2.0.0-30", "license": "MIT", "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "@typescript-eslint/eslint-plugin": "^7.8.0", "@typescript-eslint/parser": "^7.8.0", "eslint-plugin-import": "^2.29.1" @@ -10675,7 +10653,6 @@ "node": ">=18" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-typescript": "2.0.0-30", "eslint": "^8.49.0", "typescript": ">=5.0.0" } @@ -10683,6 +10660,7 @@ "packages/eslint-npm-hoist-packages": { "name": "@code-style/eslint-npm-hoist-packages", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.1.0", @@ -10699,6 +10677,7 @@ "packages/eslint-npm-hoist-packages-esmodule": { "name": "@code-style/eslint-npm-hoist-packages-esmodule", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "eslint-plugin-import": "^2.28.1" @@ -10710,6 +10689,7 @@ "packages/eslint-npm-hoist-packages-jest": { "name": "@code-style/eslint-npm-hoist-packages-jest", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "eslint-plugin-jest": "^27.4.0" @@ -10721,6 +10701,7 @@ "packages/eslint-npm-hoist-packages-nextjs": { "name": "@code-style/eslint-npm-hoist-packages-nextjs", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "@next/eslint-plugin-next": "^14.1.1" @@ -10732,6 +10713,7 @@ "packages/eslint-npm-hoist-packages-node": { "name": "@code-style/eslint-npm-hoist-packages-node", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "eslint-plugin-n": "^17.4.0" @@ -10740,66 +10722,10 @@ "node": ">=18" } }, - "packages/eslint-npm-hoist-packages-node/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "packages/eslint-npm-hoist-packages-node/node_modules/eslint-plugin-n": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.4.0.tgz", - "integrity": "sha512-RtgGgNpYxECwE9dFr+D66RtbN0B8r/fY6ZF8EVsmK2YnZxE8/n9LNQhgnkL9z37UFZjYVmvMuC32qu7fQBsLVQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "enhanced-resolve": "^5.15.0", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^15.0.0", - "ignore": "^5.2.4", - "minimatch": "^9.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": ">=8.23.0" - } - }, - "packages/eslint-npm-hoist-packages-node/node_modules/globals": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.1.0.tgz", - "integrity": "sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/eslint-npm-hoist-packages-node/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "packages/eslint-npm-hoist-packages-react": { "name": "@code-style/eslint-npm-hoist-packages-react", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "eslint-plugin-jsx-a11y": "^6.7.1", @@ -10813,6 +10739,7 @@ "packages/eslint-npm-hoist-packages-typescript": { "name": "@code-style/eslint-npm-hoist-packages-typescript", "version": "2.0.0-30", + "extraneous": true, "license": "MIT", "dependencies": { "@typescript-eslint/eslint-plugin": "^7.8.0", diff --git a/packages/eslint-config-esmodule/base.yaml b/packages/eslint-config-esmodule/base.yaml deleted file mode 100644 index dfab3feb..00000000 --- a/packages/eslint-config-esmodule/base.yaml +++ /dev/null @@ -1,12 +0,0 @@ -plugins: - - 'eslint-plugin-import' - -parserOptions: - sourceType: 'module' - -rules: - # Disallow commonjs modules. - import/no-commonjs: 'error' - - # Turn off the `import` ban from `@code-style/eslint-config/rule-sets/imports.yaml` - no-restricted-syntax: 'off' diff --git a/packages/eslint-config-esmodule/package.json b/packages/eslint-config-esmodule/package.json index f5d96882..539baeab 100644 --- a/packages/eslint-config-esmodule/package.json +++ b/packages/eslint-config-esmodule/package.json @@ -17,20 +17,25 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./*": "./dist/*.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/base.yaml" + "/dist" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-import": "^2.28.1" }, "devDependencies": { @@ -39,7 +44,6 @@ "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-esmodule": "2.0.0-30", "eslint": "^8.49.0" }, "engines": { diff --git a/packages/eslint-config-esmodule/src/base.ts b/packages/eslint-config-esmodule/src/base.ts new file mode 100644 index 00000000..088b35af --- /dev/null +++ b/packages/eslint-config-esmodule/src/base.ts @@ -0,0 +1,21 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + plugins: ['eslint-plugin-import'], + + parserOptions: { + sourceType: 'module', + }, + + rules: { + /** Disallow commonjs modules. */ + 'import/no-commonjs': 'error', + + // TODO: this could turn off other `no-restricted-syntax1 rules unintentionally + /** Turn off the `import` ban from `@code-style/eslint-config/rule-sets/imports.yaml` */ + 'no-restricted-syntax': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config-esmodule/tsconfig.build.json b/packages/eslint-config-esmodule/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-esmodule/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-esmodule/tsconfig.json b/packages/eslint-config-esmodule/tsconfig.json new file mode 100644 index 00000000..0611a855 --- /dev/null +++ b/packages/eslint-config-esmodule/tsconfig.json @@ -0,0 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs +{ + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] +} diff --git a/packages/eslint-config-jest/base.yaml b/packages/eslint-config-jest/base.yaml deleted file mode 100644 index 35a25f3e..00000000 --- a/packages/eslint-config-jest/base.yaml +++ /dev/null @@ -1,29 +0,0 @@ -overrides: - - files: - - '**/test/**' - - '**/__test__/**' - - '*.test.*' - - '*.spec.*' - - '*.unit.*' - - '*.e2e.*' - extends: - - 'plugin:eslint-plugin-jest/recommended' - settings: - jest: - version: 'detect' - - rules: - # Disallow `return` statements in tests. - jest/no-test-return-statement: 'error' - - # Prefer Jest comparators instead of boolean comparisons. - # This leads to better test failure messages. - jest/prefer-comparison-matcher: 'error' - jest/prefer-equality-matcher: 'error' - - # Prefer Jest's `expect(foo()).resolve` instead of `expect(await foo())`. - # This leads to better test failure messages. - jest/prefer-expect-resolves: 'error' - - # Require Jest hooks to be inside a `describe`. - jest/require-top-level-describe: 'error' diff --git a/packages/eslint-config-jest/lenient.yaml b/packages/eslint-config-jest/lenient.yaml deleted file mode 100644 index e6c4b825..00000000 --- a/packages/eslint-config-jest/lenient.yaml +++ /dev/null @@ -1,15 +0,0 @@ -overrides: - - files: - - '**/test/**' - - '**/__test__/**' - - '*.test.*' - - '*.spec.*' - - '*.unit.*' - - '*.e2e.*' - rules: - # Allow boolean comparisons instead of the equivalent Jest method. - jest/prefer-comparison-matcher: 'off' - jest/prefer-equality-matcher: 'off' - - # Allow `expect(await foo())`. - jest/prefer-expect-resolves: 'off' diff --git a/packages/eslint-config-jest/package.json b/packages/eslint-config-jest/package.json index f6090843..27101759 100644 --- a/packages/eslint-config-jest/package.json +++ b/packages/eslint-config-jest/package.json @@ -17,29 +17,32 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./lenient": "./lenient.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./base": "./dist/base.js", + "./lenient": "./dist/lenient.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/base.yaml", - "/lenient.yaml" + "/dist" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-jest": "^27.4.0" }, "devDependencies": { "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-jest": "2.0.0-30", "eslint": "^8.49.0", "jest": "*" }, diff --git a/packages/eslint-config-jest/src/base.ts b/packages/eslint-config-jest/src/base.ts new file mode 100644 index 00000000..756e6441 --- /dev/null +++ b/packages/eslint-config-jest/src/base.ts @@ -0,0 +1,42 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; +import { test_file_patterns } from './utils'; + +const config: ESLint.ConfigData = { + overrides: [ + { + files: test_file_patterns, + extends: ['plugin:eslint-plugin-jest/recommended'], + settings: { + jest: { + version: 'detect', + }, + }, + rules: { + /** Disallow `return` statements in tests. */ + 'jest/no-test-return-statement': 'error', + + /** + * Prefer Jest comparators instead of boolean comparisons. + * This leads to better test failure messages. + */ + 'jest/prefer-comparison-matcher': 'error', + 'jest/prefer-equality-matcher': 'error', + + /** + * Prefer Jest's `expect(foo()).resolve` instead of `expect(await foo())`. + * This leads to better test failure messages. + */ + 'jest/prefer-expect-resolves': 'error', + + /** Require Jest hooks to be inside a `describe`. */ + 'jest/require-top-level-describe': 'error', + + /** Require blocks to have valid titles. */ + 'jest/valid-title': ['error', { ignoreTypeOfDescribeName: true }], + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config-jest/src/lenient.ts b/packages/eslint-config-jest/src/lenient.ts new file mode 100644 index 00000000..cbc16ace --- /dev/null +++ b/packages/eslint-config-jest/src/lenient.ts @@ -0,0 +1,20 @@ +import type { ESLint } from 'eslint'; +import { test_file_patterns } from './utils'; + +const config: ESLint.ConfigData = { + overrides: [ + { + files: test_file_patterns, + rules: { + /** Allow boolean comparisons instead of the equivalent Jest method. */ + 'jest/prefer-comparison-matcher': 'off', + 'jest/prefer-equality-matcher': 'off', + + /** Allow `expect(await foo())`. */ + 'jest/prefer-expect-resolves': 'off', + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config-jest/src/utils.ts b/packages/eslint-config-jest/src/utils.ts new file mode 100644 index 00000000..17660bec --- /dev/null +++ b/packages/eslint-config-jest/src/utils.ts @@ -0,0 +1,8 @@ +export const test_file_patterns = [ + '**/test/**', + '**/__test__/**', + '*.test.*', + '*.spec.*', + '*.unit.*', + '*.e2e.*', +]; diff --git a/packages/eslint-config-jest/tsconfig.build.json b/packages/eslint-config-jest/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-jest/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-jest/tsconfig.json b/packages/eslint-config-jest/tsconfig.json new file mode 100644 index 00000000..0611a855 --- /dev/null +++ b/packages/eslint-config-jest/tsconfig.json @@ -0,0 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs +{ + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] +} diff --git a/packages/eslint-config-nextjs/base.yaml b/packages/eslint-config-nextjs/base.yaml deleted file mode 100644 index e795fd14..00000000 --- a/packages/eslint-config-nextjs/base.yaml +++ /dev/null @@ -1,6 +0,0 @@ -extends: - - 'plugin:@next/eslint-plugin-next/recommended' - -rules: - # NextJS requires page components to be default exports - import/no-default-export: 'off' diff --git a/packages/eslint-config-nextjs/package.json b/packages/eslint-config-nextjs/package.json index 370e6f45..6d4def70 100644 --- a/packages/eslint-config-nextjs/package.json +++ b/packages/eslint-config-nextjs/package.json @@ -16,21 +16,26 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./*": "./dist/*.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/base.yaml" + "/dist" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { - "@next/eslint-plugin-next": "^14.1.1" + "@next/eslint-plugin-next": "^14.1.1", + "@rushstack/eslint-patch": "^1.10.2" }, "devDependencies": { "@types/react": "^18.2.23", @@ -38,7 +43,6 @@ "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-react": "2.0.0-30", "eslint": "^8.49.0", "next": "*" }, diff --git a/packages/eslint-config-nextjs/src/base.ts b/packages/eslint-config-nextjs/src/base.ts new file mode 100644 index 00000000..96c530b4 --- /dev/null +++ b/packages/eslint-config-nextjs/src/base.ts @@ -0,0 +1,12 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + extends: ['plugin:@next/eslint-plugin-next/recommended'], + rules: { + /** NextJS requires page components to be default exports. */ + 'import/no-default-export': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config-nextjs/tsconfig.build.json b/packages/eslint-config-nextjs/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-nextjs/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-nextjs/tsconfig.json b/packages/eslint-config-nextjs/tsconfig.json new file mode 100644 index 00000000..0611a855 --- /dev/null +++ b/packages/eslint-config-nextjs/tsconfig.json @@ -0,0 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs +{ + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] +} diff --git a/packages/eslint-config-node/base.yaml b/packages/eslint-config-node/base.yaml deleted file mode 100644 index d5f40b88..00000000 --- a/packages/eslint-config-node/base.yaml +++ /dev/null @@ -1,103 +0,0 @@ -extends: - - 'plugin:eslint-plugin-n/recommended-module' - -parserOptions: - ecmaVersion: 2022 # Version is inline with Node 16 - sourceType: commonjs - -env: - node: true - -# `plugin:n/recommended-module` disables some globals we still want -globals: - # TODO(1): detect if project is type: module or not and remove the globals if so - __dirname: 'readonly' - __filename: 'readonly' - require: 'readonly' - module: 'writable' - -rules: - # Allow unspecified radix in `parseInt` since Node has a consistent radix. - radix: 'off' - - # Disallow using `process.env`. - # Any environment config reading should be in a specific config module. - # This simplifies understanding of the affects of config variables, as well - # as helping to ease error handling. - n/no-process-env: 'error' - - # Require `return` upon callback. - # Not returning immediately makes it easy to continue executing code after - # what would usually be considered the end of method. - n/callback-return: ['error', ['callback', 'cb', 'next']] - - # Disallow `require()` outside of the top-level module scope to encourage a - # consistent style. - n/global-require: 'error' - - # Require error handling in callbacks. - n/handle-callback-err: ['error', '^.*[eE]rr(or)?$'] - - # Disallow mixing regular variable and `require` declarations to encourage a - # consistent style. - n/no-mixed-requires: 'error' - - # Disallow use of new operator with the `require` function to encourage a - # consistent style. - n/no-new-require: 'error' - - # Disallow string concatenation with `__dirname` and `__filename`. - # Not all environments use the same path seperator (looking at you, Windows). - n/no-path-concat: 'error' - - # Allow usage of all node modules. - n/no-restricted-import: 'off' - n/no-restricted-require: 'off' - - # Disallow use of synchronous methods that have an async alternative. - # Using synchronous methods ties up the thread, preventing other requests - # from being handled while waiting on I/O. - n/no-sync: 'error' - - # Defer to import/no-extraneous-dependencies. - n/no-extraneous-import: 'off' - n/no-extraneous-require: 'off' - - # Require `module.exports` for commonjs to encourage a consistent style. - n/exports-style: ['error', 'module.exports'] - - # Require imports instead of globals. - n/prefer-global/buffer: ['error', 'never'] - n/prefer-global/text-decoder: ['error', 'never'] - n/prefer-global/text-encoder: ['error', 'never'] - n/prefer-global/url-search-params: ['error', 'never'] - n/prefer-global/url: ['error', 'never'] - - # Require promise APIs when available to encourage a consistent style. - n/prefer-promises/dns: 'error' - n/prefer-promises/fs: 'error' - - # Require callbacks to be error first callbacks. - n/no-callback-literal: 'error' - - # Check that all imports are part of our package in production. - n/no-unpublished-import: - - 'error' - - ignoreTypeImport: true - -overrides: - - files: - # test files - - '**/test/**' - - '**/__test__/**' - - '*.test.*' - - '*.spec.*' - - '*.unit.*' - - '*.e2e.*' - # config files - - '*.config.*' - - '*.configuration.*' - - 'config.*' - - 'configuration.*' - rules: - n/no-process-env: 'off' diff --git a/packages/eslint-config-node/lenient.yaml b/packages/eslint-config-node/lenient.yaml deleted file mode 100644 index ca96d51c..00000000 --- a/packages/eslint-config-node/lenient.yaml +++ /dev/null @@ -1,10 +0,0 @@ -rules: - # enforces error handling in callbacks - n/handle-callback-err: 'off' - - # disallow use of synchronous methods - n/no-sync: 'off' - - # use promise APIs - n/prefer-promises/dns: 'off' - n/prefer-promises/fs: 'off' diff --git a/packages/eslint-config-node/package.json b/packages/eslint-config-node/package.json index 1d6a44da..87c8207a 100644 --- a/packages/eslint-config-node/package.json +++ b/packages/eslint-config-node/package.json @@ -16,31 +16,33 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./lenient": "./lenient.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./*": "./dist/*.js" }, - "main": "base.yaml", + "main": "./dist/base.js", "files": [ - "/base.yaml", - "/lenient.yaml" + "/dist/" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-n": "^17.4.0" }, "devDependencies": { - "@types/eslint": "^8.44.2", + "@types/eslint": "^8.56.10", "@types/node": "^20.6.3", "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-node": "2.0.0-30", "eslint": "^8.49.0" }, "engines": { diff --git a/packages/eslint-config-node/src/base.ts b/packages/eslint-config-node/src/base.ts new file mode 100644 index 00000000..39c27cf9 --- /dev/null +++ b/packages/eslint-config-node/src/base.ts @@ -0,0 +1,125 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + extends: ['plugin:eslint-plugin-n/recommended-module'], + + parserOptions: { + ecmaVersion: 2022, // Version is inline with Node 16 + // TODO(0): should this maybe be 'script' until the upgrade to eslint 9 + sourceType: 'commonjs' as unknown as undefined, + }, + + env: { node: true }, + + // `plugin:n/recommended-module` disables some globals we still want + globals: { + // TODO(1): detect if project is type: module or not and remove the globals if so + __dirname: 'readonly', + __filename: 'readonly', + require: 'readonly', + module: 'writable', + }, + + rules: { + // Allow unspecified radix in `parseInt` since Node has a consistent radix. + radix: 'off', + + /** + * Disallow using `process.env`. + * Any environment config reading should be in a specific config module. + * This simplifies understanding of the affects of config variables, as well + * as helping to ease error handling. + */ + 'n/no-process-env': 'error', + + /** + * Require `return` upon callback. + * Not returning immediately makes it easy to continue executing code after + * what would usually be considered the end of method. + */ + 'n/callback-return': ['error', ['callback', 'cb', 'next']], + + /** + * Disallow `require()` outside of the top-level module scope to encourage a + * consistent style. + */ + 'n/global-require': 'error', + + // Require error handling in callbacks. + 'n/handle-callback-err': ['error', '^.*[eE]rr(or)?$'], + + /** + * Disallow mixing regular variable and `require` declarations to encourage a + * consistent style. + */ + 'n/no-mixed-requires': 'error', + + /** + * Disallow use of new operator with the `require` function to encourage a + * consistent style. + */ + 'n/no-new-require': 'error', + + // Disallow string concatenation with `__dirname` and `__filename`. + // Not all environments use the same path seperator (looking at you, Windows). + 'n/no-path-concat': 'error', + + // Allow usage of all node modules. + 'n/no-restricted-import': 'off', + 'n/no-restricted-require': 'off', + + /** + * Disallow use of synchronous methods that have an async alternative. + * Using synchronous methods ties up the thread, preventing other requests + * from being handled while waiting on I/O. + */ + 'n/no-sync': 'error', + + // Defer to import/no-extraneous-dependencies. + 'n/no-extraneous-import': 'off', + 'n/no-extraneous-require': 'off', + + // Require `module.exports` for commonjs to encourage a consistent style. + 'n/exports-style': ['error', 'module.exports'], + + // Require imports instead of globals. + 'n/prefer-global/buffer': ['error', 'never'], + 'n/prefer-global/text-decoder': ['error', 'never'], + 'n/prefer-global/text-encoder': ['error', 'never'], + 'n/prefer-global/url-search-params': ['error', 'never'], + 'n/prefer-global/url': ['error', 'never'], + + // Require promise APIs when available to encourage a consistent style. + 'n/prefer-promises/dns': 'error', + 'n/prefer-promises/fs': 'error', + + // Require callbacks to be error first callbacks. + 'n/no-callback-literal': 'error', + + // Check that all imports are part of our package in production. + 'n/no-unpublished-import': ['error', { ignoreTypeImport: true }], + }, + + overrides: [ + { + files: [ + // test files + '**/test/**', + '**/__test__/**', + '*.test.*', + '*.spec.*', + '*.unit.*', + '*.e2e.*', + // config files + '*.config.*', + '*.configuration.*', + 'config.*', + 'configuration.*', + ], + rules: { 'n/no-process-env': 'off' }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config-node/src/lenient.ts b/packages/eslint-config-node/src/lenient.ts new file mode 100644 index 00000000..1d605f6a --- /dev/null +++ b/packages/eslint-config-node/src/lenient.ts @@ -0,0 +1,17 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // enforces error handling in callbacks + 'n/handle-callback-err': 'off', + + // disallow use of synchronous methods + 'n/no-sync': 'off', + + // use promise APIs + 'n/prefer-promises/dns': 'off', + 'n/prefer-promises/fs': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config-node/tsconfig.build.json b/packages/eslint-config-node/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-node/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-node/tsconfig.json b/packages/eslint-config-node/tsconfig.json index 413dc603..c5cf7cb1 100644 --- a/packages/eslint-config-node/tsconfig.json +++ b/packages/eslint-config-node/tsconfig.json @@ -1,4 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs { - "extends": "../../tsconfig.json", - "exclude": [] + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/"] } diff --git a/packages/eslint-config-react/base.yaml b/packages/eslint-config-react/base.yaml deleted file mode 100644 index aeb70d5c..00000000 --- a/packages/eslint-config-react/base.yaml +++ /dev/null @@ -1,26 +0,0 @@ -extends: - - 'plugin:eslint-plugin-react/recommended' - - 'plugin:eslint-plugin-react-hooks/recommended' - - 'plugin:eslint-plugin-jsx-a11y/recommended' - -settings: - react: - version: 'detect' - -rules: - # Limit max element nesting to reduce component complexity. - # This simplifies components & enables better testing. - react/jsx-max-depth: - - 'error' - - max: 5 - - # Require class components to use ES6 classes rather than ES5 classes. - react/prefer-es6-class: 'error' - - # Require stateless components to be functional components. - react/prefer-stateless-function: 'error' - - react/no-children-prop: 'off' - - # Require iterated elements to have a `key`. - react/jsx-key: 'error' diff --git a/packages/eslint-config-react/package.json b/packages/eslint-config-react/package.json index 0723b338..87500f4a 100644 --- a/packages/eslint-config-react/package.json +++ b/packages/eslint-config-react/package.json @@ -16,20 +16,25 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./*": "./dist/*.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/base.yaml" + "/dist" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0" @@ -40,7 +45,6 @@ "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-react": "2.0.0-30", "eslint": "^8.49.0", "react": ">=16.8", "react-dom": ">=16.8" diff --git a/packages/eslint-config-react/src/base.ts b/packages/eslint-config-react/src/base.ts new file mode 100644 index 00000000..24aea1cc --- /dev/null +++ b/packages/eslint-config-react/src/base.ts @@ -0,0 +1,35 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + extends: [ + 'plugin:eslint-plugin-react/recommended', + 'plugin:eslint-plugin-react-hooks/recommended', + 'plugin:eslint-plugin-jsx-a11y/recommended', + ], + settings: { + react: { + version: 'detect', + }, + }, + rules: { + /** + * Limit max element nesting to reduce component complexity. + * This simplifies components & enables better testing. + */ + 'react/jsx-max-depth': ['error', { max: 5 }], + + /** Require class components to use ES6 classes rather than ES5 classes. */ + 'react/prefer-es6-class': 'error', + + /** Require stateless components to be functional components. */ + 'react/prefer-stateless-function': 'error', + + 'react/no-children-prop': 'off', + + /** Require iterated elements to have a `key`. */ + 'react/jsx-key': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config-react/tsconfig.build.json b/packages/eslint-config-react/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-react/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-react/tsconfig.json b/packages/eslint-config-react/tsconfig.json new file mode 100644 index 00000000..0611a855 --- /dev/null +++ b/packages/eslint-config-react/tsconfig.json @@ -0,0 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs +{ + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] +} diff --git a/packages/eslint-config-typescript/base.yaml b/packages/eslint-config-typescript/base.yaml deleted file mode 100644 index 7bc39a3c..00000000 --- a/packages/eslint-config-typescript/base.yaml +++ /dev/null @@ -1,102 +0,0 @@ -overrides: - - files: - - '*.?(m|c)@(t|j)s?(x)' - excludedFiles: '*.json' - - extends: - - 'plugin:@typescript-eslint/eslint-plugin/strict-type-checked' - - 'plugin:@typescript-eslint/eslint-plugin/stylistic-type-checked' - - 'plugin:eslint-plugin-import/typescript' - - parserOptions: - project: true - rules: - # Allow specifying a type that could otherwise be inferred. - '@typescript-eslint/no-inferrable-types': 'off' - - # Disallow unused variables. - '@typescript-eslint/no-unused-vars': - - 'warn' - - args: 'none' - destructuredArrayIgnorePattern: '^_' - - # TODO(0): throws on code that should probably be allowed - # ``` - # const foo: number | undefined = Math.random() === 0 ? 1 : undefined; - # if (foo?.toString().includes('a')) console.log('hi'); - # ``` - # Require only boolean types to be used for conditions. - '@typescript-eslint/strict-boolean-expressions': - - 'error' - - allowAny: false - allowString: false - allowNullableString: false - allowNumber: false - allowNullableNumber: false - allowNullableObject: true - allowNullableBoolean: true - - # Require switches on union types to handle all cases. - '@typescript-eslint/switch-exhaustiveness-check': 'error' - - # Disallow empty classes, unless they're decorated. - '@typescript-eslint/no-extraneous-class': - - 'error' - - allowWithDecorator: true - - # TODO: do we want this? - # Require `enum` values to be initialized in order to prevent value shifting. - # If an `enum`'s value isn't defined, Typescript will automatically pick a - # numeric value for it based on its position in the enum list. If that - # value is then used to save state into a store, and then the `enum`'s - # list of values is updated, the value in the store may not correspond with - # the intended enum value anymore. - '@typescript-eslint/prefer-enum-initializers': 'error' - - # Allow use of both `type` and `interface`. - '@typescript-eslint/consistent-type-definitions': 'off' - - # Require `private` members to be marked `readonly` when possible. - '@typescript-eslint/prefer-readonly': 'error' - - # Allow returning the correct type, even if it might be slightly confusing. - '@typescript-eslint/no-confusing-void-expression': 'off' - - '@typescript-eslint/no-empty-function': 'off' - - # Disable this rule since it doesn't work reliably. - '@typescript-eslint/consistent-generic-constructors': 'off' - - # Disable this rule until this issue is fixed. - # https://github.com/typescript-eslint/typescript-eslint/issues/7502 - '@typescript-eslint/no-base-to-string': 'off' - - # Allow comparing `enum`s to appropriate primitive values. - '@typescript-eslint/no-unsafe-enum-comparison': 'off' - - # Disable this rule since Typescript checks imports for us. - 'import/no-unresolved': 'off' - 'n/no-missing-import': 'off' - - # Disable this rule since Typescript handles these rules for us. - consistent-return: 'off' - no-invalid-this: 'off' - - # Allow any value in template literal expression. - '@typescript-eslint/restrict-template-expressions': 'off' - - # Require unbound methods to be called with their expected scope. - '@typescript-eslint/unbound-method': - - 'error' - - ignoreStatic: true - - # Disable this rule since Typescript will handle this for us. - 'promise/valid-params': 'off' - - # Allow function overload signatures. - '@typescript-eslint/unified-signatures': 'off' - - # TODO(2): create a linter rule to handle correlation between class-validator types, swagger types, and typescript types - - # Allow const requires - '@typescript-eslint/no-var-requires': 'off' diff --git a/packages/eslint-config-typescript/lenient.yaml b/packages/eslint-config-typescript/lenient.yaml deleted file mode 100644 index 8d5cbf6b..00000000 --- a/packages/eslint-config-typescript/lenient.yaml +++ /dev/null @@ -1,39 +0,0 @@ -overrides: - - files: - - '*.?(m|c)@(t|j)s?(x)' - excludedFiles: '*.json' - - rules: - # Allow some non-boolean type conditionals. - '@typescript-eslint/strict-boolean-expressions': - - 'error' - - allowAny: true - allowString: false - allowNullableString: false - allowNumber: false - allowNullableNumber: false - allowNullableObject: true - allowNullableBoolean: true - - # Don't ensure switches on union types handle all cases. - '@typescript-eslint/switch-exhaustiveness-check': 'off' - - # Allow unused vars. - '@typescript-eslint/no-unused-vars': 'off' - - # Allow `any`. - '@typescript-eslint/no-explicit-any': 'off' - '@typescript-eslint/no-unsafe-return': 'off' - '@typescript-eslint/no-unsafe-assignment': 'off' - '@typescript-eslint/no-unsafe-member-access': 'off' - '@typescript-eslint/no-unsafe-argument': 'off' - '@typescript-eslint/no-unsafe-call': 'off' - - # Allow non-null assertions. - '@typescript-eslint/no-non-null-assertion': 'off' - - # Allow for loops - '@typescript-eslint/prefer-for-of': 'off' - - # Allow floating promises - '@typescript-eslint/no-floating-promises': 'off' diff --git a/packages/eslint-config-typescript/package.json b/packages/eslint-config-typescript/package.json index 6b57fd22..1912c103 100644 --- a/packages/eslint-config-typescript/package.json +++ b/packages/eslint-config-typescript/package.json @@ -16,25 +16,28 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./lenient": "./lenient.yaml", - "./*.yaml": "./*.yaml" + ".": "./dist/base.js", + "./*": "./dist/*.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/base.yaml", - "/lenient.yaml" + "/dist" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", "lint": "concurrently --raw --group \"npm:lint:*\"", "lint:js": "eslint . --ext ts,mts,cts,js,json", "lint:types": "tsc --noEmit --pretty", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' --ignore '**/fixture?(s)/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { + "@rushstack/eslint-patch": "^1.10.2", "@typescript-eslint/eslint-plugin": "^7.8.0", "@typescript-eslint/parser": "^7.8.0", "eslint-plugin-import": "^2.29.1" @@ -47,7 +50,6 @@ "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages-typescript": "2.0.0-30", "eslint": "^8.49.0", "typescript": ">=5.0.0" }, diff --git a/packages/eslint-config-typescript/src/base.ts b/packages/eslint-config-typescript/src/base.ts new file mode 100644 index 00000000..52846111 --- /dev/null +++ b/packages/eslint-config-typescript/src/base.ts @@ -0,0 +1,120 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + overrides: [ + { + files: ['*.?(m|c)@(t|j)s?(x)'], + excludedFiles: '*.json', + + extends: [ + 'plugin:@typescript-eslint/eslint-plugin/strict-type-checked', + 'plugin:@typescript-eslint/eslint-plugin/stylistic-type-checked', + 'plugin:eslint-plugin-import/typescript', + ], + + parserOptions: { + project: true, + }, + + rules: { + /** Allow specifying a type that could otherwise be inferred. */ + '@typescript-eslint/no-inferrable-types': 'off', + + /** Disallow unused variables. */ + '@typescript-eslint/no-unused-vars': [ + 'warn', + { args: 'none', destructuredArrayIgnorePattern: '^_' }, + ], + + // TODO(0): throws on code that should probably be allowed + // ``` + // const foo: number | undefined = Math.random() === 0 ? 1 : undefined; + // if (foo?.toString().includes('a')) console.log('hi'); + // ``` + /** Require only boolean types to be used for conditions. */ + '@typescript-eslint/strict-boolean-expressions': [ + 'error', + { + allowAny: false, + allowString: false, + allowNullableString: false, + allowNumber: false, + allowNullableNumber: false, + allowNullableObject: true, + allowNullableBoolean: true, + }, + ], + + /** Require switches on union types to handle all cases. */ + '@typescript-eslint/switch-exhaustiveness-check': 'error', + + /** Disallow empty classes, unless they're decorated. */ + '@typescript-eslint/no-extraneous-class': [ + 'error', + { allowWithDecorator: true }, + ], + + // TODO: do we want this? + /** + * Require `enum` values to be initialized in order to prevent value shifting. + * If an `enum`'s value isn't defined, Typescript will automatically pick a + * numeric value for it based on its position in the enum list. If that + * value is then used to save state into a store, and then the `enum`'s + * list of values is updated, the value in the store may not correspond with + * the intended enum value anymore. + */ + '@typescript-eslint/prefer-enum-initializers': 'error', + + /** Allow use of both `type` and `interface`. */ + '@typescript-eslint/consistent-type-definitions': 'off', + + /** Require `private` members to be marked `readonly` when possible. */ + '@typescript-eslint/prefer-readonly': 'error', + + /** Allow returning the correct type, even if it might be slightly confusing. */ + '@typescript-eslint/no-confusing-void-expression': 'off', + + /** Allow empty functions */ + '@typescript-eslint/no-empty-function': 'off', + + /** Disable this rule since it doesn't work reliably. */ + '@typescript-eslint/consistent-generic-constructors': 'off', + + /** + * Disable this rule until this issue is fixed. + * https://github.com/typescript-eslint/typescript-eslint/issues/7502 + */ + '@typescript-eslint/no-base-to-string': 'off', + + /** Allow comparing `enum`s to appropriate primitive values. */ + '@typescript-eslint/no-unsafe-enum-comparison': 'off', + + /** Disable this rule since Typescript checks imports for us. */ + 'import/no-unresolved': 'off', + 'n/no-missing-import': 'off', + + /** Disable these rules since Typescript handles these rules for us. */ + 'consistent-return': 'off', + 'no-invalid-this': 'off', + 'promise/valid-params': 'off', + + /** Allow any value in template literal expression. */ + '@typescript-eslint/restrict-template-expressions': 'off', + + /** Require unbound methods to be called with their expected scope. */ + '@typescript-eslint/unbound-method': ['error', { ignoreStatic: true }], + + /** Allow function overload signatures. */ + '@typescript-eslint/unified-signatures': 'off', + + /** Allow const requires */ + '@typescript-eslint/no-var-requires': 'off', + + // TODO(2): create a linter rule to handle correlation between class-validator types, swagger types, and typescript types + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config-typescript/src/lenient.ts b/packages/eslint-config-typescript/src/lenient.ts new file mode 100644 index 00000000..6c6ede93 --- /dev/null +++ b/packages/eslint-config-typescript/src/lenient.ts @@ -0,0 +1,51 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + overrides: [ + { + files: ['*.?(m|c)@(t|j)s?(x)'], + excludedFiles: '*.json', + rules: { + /** Allow some non-boolean type conditionals. */ + '@typescript-eslint/strict-boolean-expressions': [ + 'error', + { + allowAny: true, + allowString: false, + allowNullableString: false, + allowNumber: false, + allowNullableNumber: false, + allowNullableObject: true, + allowNullableBoolean: true, + }, + ], + + /** Don't ensure switches on union types handle all cases. */ + '@typescript-eslint/switch-exhaustiveness-check': 'off', + + /** Allow unused vars. */ + '@typescript-eslint/no-unused-vars': 'off', + + /** Allow `any`. */ + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + + /** Allow non-null assertions. */ + '@typescript-eslint/no-non-null-assertion': 'off', + + /** Allow for loops. */ + '@typescript-eslint/prefer-for-of': 'off', + + /** Allow floating promises. */ + '@typescript-eslint/no-floating-promises': 'off', + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config-typescript/tsconfig.build.json b/packages/eslint-config-typescript/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config-typescript/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config-typescript/tsconfig.json b/packages/eslint-config-typescript/tsconfig.json index 9fc01da4..0611a855 100644 --- a/packages/eslint-config-typescript/tsconfig.json +++ b/packages/eslint-config-typescript/tsconfig.json @@ -1,9 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs { "extends": [ "@code-style/typescript-configs/roles/node", - "@code-style/typescript-configs/layers/esmodule" + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" ], - "compilerOptions": { "noEmit": true, "outDir": "dist/" }, - "include": ["test/"], - "exclude": ["dist/"] + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] } diff --git a/packages/eslint-config/base.yaml b/packages/eslint-config/base.yaml deleted file mode 100644 index 32fda27c..00000000 --- a/packages/eslint-config/base.yaml +++ /dev/null @@ -1,29 +0,0 @@ -extends: - - 'eslint:recommended' - - 'plugin:prettier/recommended' - - 'plugin:eslint-plugin-promise/recommended' - # TODO(0): consider switching to `eslint-plugin-i` - - 'plugin:eslint-plugin-import/recommended' - - 'plugin:@eslint-community/eslint-plugin-eslint-comments/recommended' - - - './rule-sets/bugs.yaml' - - './rule-sets/deprecated.yaml' - - './rule-sets/footguns.yaml' - - './rule-sets/imports.yaml' - - './rule-sets/miscellaneous.yaml' - - './rule-sets/modern-code.yaml' - - './rule-sets/promises.yaml' - - './rule-sets/readability.yaml' - - './rule-sets/security.yaml' - - - './overrides/index.yaml' - -parserOptions: - ecmaVersion: 2022 # Version is inline with Node 16 - -env: - commonjs: true - -ignorePatterns: - - '**/dist/**' - - '!.*' diff --git a/packages/eslint-config/lenient.yaml b/packages/eslint-config/lenient.yaml deleted file mode 100644 index ad1afe57..00000000 --- a/packages/eslint-config/lenient.yaml +++ /dev/null @@ -1,47 +0,0 @@ -rules: - # Allow symbols to not have a description. - symbol-description: 'off' - - # Allow string concatenation. - prefer-template: 'off' - - # Allow `.apply()`. - prefer-spread: 'off' - - # Allow synchronous loops. - no-await-in-loop: 'off' - - # Allow uncaught promise errors. - promise/catch-or-return: 'off' - - # Allow non-dot notation. - dot-notation: 'off' - - # Allow files to be any length. - max-lines: 'off' - - # Allow parameter reassigning. - no-param-reassign: 'off' - - # Allow any import formatting - import/order: 'off' - import/newline-after-import: 'off' - - # Allow node globals - n/prefer-global/buffer: 'off' - n/prefer-global/text-decoder: 'off' - n/prefer-global/text-encoder: 'off' - n/prefer-global/url-search-params: 'off' - n/prefer-global/url: 'off' - - # Allow reading from process.env from any file - n/no-process-env: 'off' - - # Allow void promises - promise/always-return: 'off' - - # Allow throwing literals - no-throw-literal: 'off' - - # Allow unused vars - no-unused-vars: 'off' diff --git a/packages/eslint-config/overrides/index.yaml b/packages/eslint-config/overrides/index.yaml deleted file mode 100644 index 6132e63d..00000000 --- a/packages/eslint-config/overrides/index.yaml +++ /dev/null @@ -1,12 +0,0 @@ -overrides: - - files: '*.json' - extends: './json.yaml' - - - files: - - '**/test/**' - - '**/__test__/**' - - '*.test.*' - - '*.spec.*' - - '*.unit.*' - - '*.e2e.*' - extends: './testing.yaml' diff --git a/packages/eslint-config/overrides/json.yaml b/packages/eslint-config/overrides/json.yaml deleted file mode 100644 index b28c9a7a..00000000 --- a/packages/eslint-config/overrides/json.yaml +++ /dev/null @@ -1,6 +0,0 @@ -plugins: - - 'eslint-plugin-json-files' - -rules: - # eslint-plugin-prettier breaks JSON linting (https://github.com/prettier/eslint-plugin-prettier/issues/570) - prettier/prettier: 'off' diff --git a/packages/eslint-config/overrides/testing.yaml b/packages/eslint-config/overrides/testing.yaml deleted file mode 100644 index 224cbb3f..00000000 --- a/packages/eslint-config/overrides/testing.yaml +++ /dev/null @@ -1,31 +0,0 @@ -rules: - # Allow console logging in tests - no-console: 'off' - - # Allow test to import unpublished files. - n/no-unpublished-import: 'off' - - # Allow test files to be any length. - max-lines: 'off' - - # Don't require dot notation in tests. - # This can be useful for accessing Typescript `private` properties & methods - dot-notation: 'off' - '@typescript-eslint/dot-notation': 'off' - - # Allow `any` in tests. - '@typescript-eslint/no-explicit-any': 'off' - '@typescript-eslint/no-unsafe-return': 'off' - '@typescript-eslint/no-unsafe-assignment': 'off' - '@typescript-eslint/no-unsafe-member-access': 'off' - '@typescript-eslint/no-unsafe-argument': 'off' - - # Allow non-null assertions in tests. - '@typescript-eslint/no-non-null-assertion': 'off' - '@typescript-eslint/no-non-null-asserted-optional-chain': 'off' - - # Simplify testing methods. - '@typescript-eslint/unbound-method': 'off' - - # Allow tests to throw literals. - '@typescript-eslint/no-throw-literal': 'off' diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 45c2d6f3..3f711907 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -16,25 +16,29 @@ }, "license": "MIT", "author": "Louis Orleans ", + "type": "commonjs", "exports": { - ".": "./base.yaml", - "./base": "./base.yaml", - "./lenient": "./lenient.yaml", - "./*.yaml": "./*.yaml", - "./rule-sets/*.yaml": "./rule-sets/*.yaml" + ".": "./dist/base.js", + "./base": "./dist/base.js", + "./lenient": "./dist/lenient.js", + "./rule-sets/*": "./dist/rule-sets/*.js", + "./overrides/*": "./dist/overrides/*.js" }, - "main": "base.yaml", + "main": "dist/base.js", "files": [ - "/rule-sets/", - "/base.yaml", - "/lenient.yaml" + "/dist/" ], "scripts": { + "build": "concurrently --raw --group 'npm:build:*'", + "build:js": "esbuild --tsconfig=tsconfig.build.json $(glob 'src/**/*.?(c|m)[jt]s' --ignore '**/*.spec.*') --outdir=dist/ --sourcemap=inline --platform=node --target=node18 --format=cjs", + "build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly", + "prepublishOnly": "npm run build", "test": "node $NODE_OPTS --require tsm --test $(glob --ignore '**/node_modules/**' --ignore '**/dist/**' '**/*[.-_]test.?(c|m)[jt]s' '**/test?(-*).?(c|m)[jt]s' '**/test/**/*.?(c|m)[jt]s')", "test:debug": "NODE_OPTS='--inspect-brk' npm run test" }, "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.1.0", + "@rushstack/eslint-patch": "^1.10.2", "eslint": "^8.49.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", @@ -48,7 +52,6 @@ "tsm": "^2.3.0" }, "peerDependencies": { - "@code-style/eslint-npm-hoist-packages": "2.0.0-30", "prettier": "^3.1.0" }, "engines": { @@ -57,10 +60,5 @@ "publishConfig": { "access": "public", "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } } } diff --git a/packages/eslint-config/rule-sets/bugs.yaml b/packages/eslint-config/rule-sets/bugs.yaml deleted file mode 100644 index 9f119d78..00000000 --- a/packages/eslint-config/rule-sets/bugs.yaml +++ /dev/null @@ -1,21 +0,0 @@ -rules: - # Disallows meaningless comparisons to self. - no-self-compare: 'error' - - # Disallows using `this` when `this` is undefined. - no-invalid-this: 'error' - - # Catches some race conditions, but can lead to false-positives. - require-atomic-updates: ['warn', { allowProperties: true }] - - # Disallows usage of `new` for certain globals functions. - no-new-native-nonconstructor: 'error' - - # Disallows throwing literal values, preferring objects extending `Error` instead. - # Throwing `Errors` improves the traceability of exceptions. - no-throw-literal: 'error' - - # Ensures that binary comparisons can possibly change value. - # If a binary expression comparison can't change value, then you're likely doing something you didn't intend. - # https://eslint.org/blog/2022/07/interesting-bugs-caught-by-no-constant-binary-expression/ - no-constant-binary-expression: 'error' diff --git a/packages/eslint-config/rule-sets/deprecated.yaml b/packages/eslint-config/rule-sets/deprecated.yaml deleted file mode 100644 index 43d0061c..00000000 --- a/packages/eslint-config/rule-sets/deprecated.yaml +++ /dev/null @@ -1,9 +0,0 @@ -rules: - # `__iterator__` is deprecated. - no-iterator: 'error' - - # `__proto__` is deprecated. - no-proto: 'error' - - # Disallows allow `var`, preferring `let` or `const` instead. - no-var: 'error' diff --git a/packages/eslint-config/rule-sets/footguns.yaml b/packages/eslint-config/rule-sets/footguns.yaml deleted file mode 100644 index d6036aae..00000000 --- a/packages/eslint-config/rule-sets/footguns.yaml +++ /dev/null @@ -1,68 +0,0 @@ -rules: - # TODO(0): look into where parseInt isn't base 10 - # Require `parseInt` to have a radix specified since some browsers don't default to base 10. - radix: 'error' - - # Require the use of `===` since `==` has some weird behavior. - eqeqeq: ['error', 'smart'] - - # Prefer binary, octal, and hexadecimal literals instead of `parseInt('F', 16)`. - prefer-numeric-literals: 'error' - - # Ensure that functional array methods are chainable. - array-callback-return: 'error' - - # Disallow returning in a constructor. - no-constructor-return: 'error' - - # Disallow array constructors with multiple params. - no-array-constructor: 'error' - - # Disallow `arguments.caller`. - no-caller: 'error' - - # Disallow monkeypatching. - no-extend-native: 'error' - - # TODO(2): are we sure we really want this? it's not _really_ necessary - # Disallow sequences. - no-sequences: ['error', { allowInParentheses: false }] - - # Disallow the `void` keyword. - no-void: - - 'error' - - allowAsStatement: true - - # Disallow bitwise operators, which are usually typos for boolean operators - no-bitwise: 'error' - - # Ensure regexp uses certain flags. - require-unicode-regexp: 'error' - - # Prevent unintentional numeric literal values (eg: `071 === 51`). - no-octal: 'error' - - # Prevent labels from sharing their name with variable. - no-label-var: 'error' - - # Disallow allow empty blocks. - no-empty: - - 'error' - - 'allowEmptyCatch': true - -overrides: - - files: '*.json' - rules: - # Prevent having the same package in dependencies and devDependencies. - json-files/require-unique-dependency-names: 'error' - - # Require that specific ranges are specified in `package.json` `dependencies`. - json-files/restrict-ranges: - - 'error' - - versionHint: 'caret' - dependencyTypes: - - 'dependencies' - - 'devDependencies' - - # Require that `engines` are specified in `package.json`. - json-files/require-engines: 'error' diff --git a/packages/eslint-config/rule-sets/imports.yaml b/packages/eslint-config/rule-sets/imports.yaml deleted file mode 100644 index 5290aafc..00000000 --- a/packages/eslint-config/rule-sets/imports.yaml +++ /dev/null @@ -1,63 +0,0 @@ -rules: - # Warn about deprecated imports. - import/no-deprecated: 'warn' - - # Disallow exporting mutable vars. - import/no-mutable-exports: 'error' - - # Disallow AMD modules. - import/no-amd: 'error' - - # Disallow mixing ESM with commonjs exports. - import/no-import-module-exports: 'error' - - # Disallow importing yourself. - import/no-self-import: 'error' - - # Disallow webpack imports. - import/no-webpack-loader-syntax: 'error' - - # Ensure imports come first in file. - import/first: 'error' - - # Ensure imports are seperated from the rest of the file. - import/newline-after-import: 'error' - - # Disallow default exports. - import/no-default-export: 'error' - - # Ensure consistent ordering of imports. - import/order: - - 'warn' - - groups: - - 'builtin' - - 'external' - - 'internal' - newlines-between: 'ignore' - - # Use `import/order` instead. - sort-imports: 'off' - - # disable ES Module import/export - no-restricted-syntax: - - 'error' - - selector: 'ImportDeclaration' - message: 'ES Module import not allowed' - - selector: 'ExportNamedDeclaration' - message: 'ES Module export not allowed' - - selector: 'ExportDefaultDeclaration' - message: 'ES Module export not allowed' - - selector: 'ExportAllDeclaration' - message: 'ES Module export not allowed' - - selector: 'TSExportAssignment' - message: 'ES Module export not allowed' - -overrides: - - files: - - 'jest.config.*js' - rules: - import/no-default-export: 'off' - - files: - - './*.config.js' - rules: - import/no-commonjs: 'off' diff --git a/packages/eslint-config/rule-sets/miscellaneous.yaml b/packages/eslint-config/rule-sets/miscellaneous.yaml deleted file mode 100644 index dbbcdc1b..00000000 --- a/packages/eslint-config/rule-sets/miscellaneous.yaml +++ /dev/null @@ -1,17 +0,0 @@ -rules: - # Disallow `console` and `alert` calls. - # Neither of these methods should be used in production. - no-console: 'error' - no-alert: 'error' - - # Warn about prettier style issues. - prettier/prettier: 'warn' - - # Disallow renaming `import`, `export`, and destructured assignments to the same name. - no-useless-rename: 'error' - - # Require `symbol`s to have a description. - symbol-description: 'error' - - # Require `switch`'s `default` case to be last. - default-case-last: 'error' diff --git a/packages/eslint-config/rule-sets/modern-code.yaml b/packages/eslint-config/rule-sets/modern-code.yaml deleted file mode 100644 index bc9713fc..00000000 --- a/packages/eslint-config/rule-sets/modern-code.yaml +++ /dev/null @@ -1,15 +0,0 @@ -rules: - # Prefer template literals instead of string concatenation. - prefer-template: 'error' - - # Disallow using `.apply()`. - prefer-spread: 'error' - - # Prefer a rest parameter instead of `arguments`. - prefer-rest-params: 'error' - - # Prefer using arrow functions as callbacks. - prefer-arrow-callback: ['error', { allowNamedFunctions: true }] - - # Prefer `const` for vars that are never modified. - prefer-const: 'error' diff --git a/packages/eslint-config/rule-sets/promises.yaml b/packages/eslint-config/rule-sets/promises.yaml deleted file mode 100644 index 5649294f..00000000 --- a/packages/eslint-config/rule-sets/promises.yaml +++ /dev/null @@ -1,21 +0,0 @@ -rules: - # Require errors from promises are caught. - promise/catch-or-return: ['error', { allowThen: true }] - - # Disallow calling resolve multiple times. - promise/no-multiple-resolved: 'error' - - # Allow nesting promises. - promise/no-nesting: 'off' - - # Allow using promises inside of callbacks. - promise/no-promise-in-callback: 'off' - - # Ensure the proper number of arguments are passed to `Promise` functions. - promise/valid-params: 'error' - - # Require `async` functions to contain an `await`. - require-await: 'error' - - # Prefer using `Promise.all` instead of synchronous loops. - no-await-in-loop: 'error' diff --git a/packages/eslint-config/rule-sets/readability.yaml b/packages/eslint-config/rule-sets/readability.yaml deleted file mode 100644 index 5dad3c1d..00000000 --- a/packages/eslint-config/rule-sets/readability.yaml +++ /dev/null @@ -1,24 +0,0 @@ -rules: - # Prefer `else if` instead of a lonely `if` inside of an `else`. - no-lonely-if: 'error' - - # Require dot notation when possible. - dot-notation: 'error' - - # TODO: what should our max be? should we even have one? - # Disallow excessively large files which would be better to be broken up. - max-lines: ['error', { max: 2000, skipBlankLines: true, skipComments: true }] - - # Disallow reassigning method params, treating them as `const`. - no-param-reassign: 'warn' - - no-unused-vars: - - 'warn' - - args: 'none' - destructuredArrayIgnorePattern: '^_' - -overrides: - - files: '*.json' - rules: - # Require keys in package.json to be sorted, improving readability & consistency across projects. - json-files/sort-package-json: 'warn' diff --git a/packages/eslint-config/rule-sets/security.yaml b/packages/eslint-config/rule-sets/security.yaml deleted file mode 100644 index 82df4250..00000000 --- a/packages/eslint-config/rule-sets/security.yaml +++ /dev/null @@ -1,4 +0,0 @@ -rules: - # Disallow `eval`. - no-eval: 'error' - no-implied-eval: 'error' diff --git a/packages/eslint-config/src/base.ts b/packages/eslint-config/src/base.ts new file mode 100644 index 00000000..ce9dc991 --- /dev/null +++ b/packages/eslint-config/src/base.ts @@ -0,0 +1,33 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + extends: [ + 'eslint:recommended', + 'plugin:prettier/recommended', + 'plugin:eslint-plugin-promise/recommended', + 'plugin:eslint-plugin-import/recommended', + 'plugin:@eslint-community/eslint-plugin-eslint-comments/recommended', + + './rule-sets/bugs.js', + './rule-sets/deprecated.js', + './rule-sets/footguns.js', + './rule-sets/imports.js', + './rule-sets/miscellaneous.js', + './rule-sets/modern-code.js', + './rule-sets/promises.js', + './rule-sets/readability.js', + './rule-sets/security.js', + + './overrides/index.js', + ], + parserOptions: { + ecmaVersion: 2022, + }, + env: { + commonjs: true, + }, + ignorePatterns: ['**/dist/**', '**/out/**', '**/coverage/**', '!.*'], +}; + +export = config; diff --git a/packages/eslint-config/src/lenient.ts b/packages/eslint-config/src/lenient.ts new file mode 100644 index 00000000..6f32c7f0 --- /dev/null +++ b/packages/eslint-config/src/lenient.ts @@ -0,0 +1,27 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + 'symbol-description': 'off', + 'prefer-template': 'off', + 'prefer-spread': 'off', + 'no-await-in-loop': 'off', + 'promise/catch-or-return': 'off', + 'dot-notation': 'off', + 'max-lines': 'off', + 'no-param-reassign': 'off', + 'import/order': 'off', + 'import/newline-after-import': 'off', + 'n/prefer-global/buffer': 'off', + 'n/prefer-global/text-decoder': 'off', + 'n/prefer-global/text-encoder': 'off', + 'n/prefer-global/url-search-params': 'off', + 'n/prefer-global/url': 'off', + 'n/no-process-env': 'off', + 'promise/always-return': 'off', + 'no-throw-literal': 'off', + 'no-unused-vars': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/overrides/index.ts b/packages/eslint-config/src/overrides/index.ts new file mode 100644 index 00000000..92f91b0f --- /dev/null +++ b/packages/eslint-config/src/overrides/index.ts @@ -0,0 +1,23 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + overrides: [ + { + files: ['*.json'], + extends: './json.js', + }, + { + files: [ + '**/test/**', + '**/__test__/**', + '*.test.*', + '*.spec.*', + '*.unit.*', + '*.e2e.*', + ], + extends: './testing.js', + }, + ], +}; + +export = config; diff --git a/packages/eslint-config/src/overrides/json.ts b/packages/eslint-config/src/overrides/json.ts new file mode 100644 index 00000000..774e1a71 --- /dev/null +++ b/packages/eslint-config/src/overrides/json.ts @@ -0,0 +1,10 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // eslint-plugin-prettier breaks JSON linting (https://github.com/prettier/eslint-plugin-prettier/issues/570) + 'prettier/prettier': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/overrides/testing.ts b/packages/eslint-config/src/overrides/testing.ts new file mode 100644 index 00000000..01825d9a --- /dev/null +++ b/packages/eslint-config/src/overrides/testing.ts @@ -0,0 +1,40 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Allow console logging in tests + 'no-console': 'off', + + // Allow test to import unpublished files. + 'n/no-unpublished-import': 'off', + + // Allow test files to be any length. + 'max-lines': 'off', + + /** + * Don't require dot notation in tests. + * This can be useful for accessing Typescript `private` properties & methods. + */ + 'dot-notation': 'off', + '@typescript-eslint/dot-notation': 'off', + + // Allow `any` in tests. + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + + // Allow non-null assertions in tests. + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', + + // Simplify testing methods. + '@typescript-eslint/unbound-method': 'off', + + // Allow tests to throw literals. + '@typescript-eslint/no-throw-literal': 'off', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/bugs.ts b/packages/eslint-config/src/rule-sets/bugs.ts new file mode 100644 index 00000000..cd7bcf12 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/bugs.ts @@ -0,0 +1,32 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Disallows meaningless comparisons to self. + 'no-self-compare': 'error', + + // Disallows using `this` when `this` is undefined. + 'no-invalid-this': 'error', + + // Catches some race conditions, but can lead to false-positives. + 'require-atomic-updates': ['warn', { allowProperties: true }], + + // Disallows usage of `new` for certain globals functions. + 'no-new-native-nonconstructor': 'error', + + /** + * Disallows throwing literal values, preferring objects extending `Error` instead. + * Throwing `Errors` improves the traceability of exceptions. + */ + 'no-throw-literal': 'error', + + /** + * Ensures that binary comparisons can possibly change value. + * If a binary expression comparison can't change value, then you're likely doing something you didn't intend. + * https://eslint.org/blog/2022/07/interesting-bugs-caught-by-no-constant-binary-expression/ + */ + 'no-constant-binary-expression': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/deprecated.ts b/packages/eslint-config/src/rule-sets/deprecated.ts new file mode 100644 index 00000000..d5dbccc7 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/deprecated.ts @@ -0,0 +1,16 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // `__iterator__` is deprecated. + 'no-iterator': 'error', + + // `__proto__` is deprecated. + 'no-proto': 'error', + + // Disallows allow `var`, preferring `let` or `const` instead. + 'no-var': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/footguns.ts b/packages/eslint-config/src/rule-sets/footguns.ts new file mode 100644 index 00000000..7d460550 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/footguns.ts @@ -0,0 +1,77 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // TODO(0): look into where parseInt isn't base 10 + // Require `parseInt` to have a radix specified since some browsers don't default to base 10. + radix: 'error', + + // Require the use of `===` since `==` has some weird behavior. + eqeqeq: ['error', 'smart'], + + // Prefer binary, octal, and hexadecimal literals instead of `parseInt('F', 16)`. + 'prefer-numeric-literals': 'error', + + // Ensure that functional array methods are chainable. + 'array-callback-return': 'error', + + // Disallow returning in a constructor. + 'no-constructor-return': 'error', + + // Disallow array constructors with multiple params. + 'no-array-constructor': 'error', + + // Disallow `arguments.caller`. + 'no-caller': 'error', + + // Disallow monkeypatching. + 'no-extend-native': 'error', + + // TODO(2): are we sure we really want this? it's not _really_ necessary + // Disallow sequences. + 'no-sequences': ['error', { allowInParentheses: false }], + + // Disallow the `void` keyword. + 'no-void': ['error', { allowAsStatement: true }], + + // Disallow bitwise operators, which are usually typos for boolean operators + 'no-bitwise': 'error', + + // Ensure regexp uses certain flags. + 'require-unicode-regexp': 'error', + + // Prevent unintentional numeric literal values (eg: `071 === 51`). + 'no-octal': 'error', + + // Prevent labels from sharing their name with variable. + 'no-label-var': 'error', + + // Disallow allow empty blocks. + 'no-empty': ['error', { allowEmptyCatch: true }], + }, + overrides: [ + { + files: '*.json', + plugins: ['eslint-plugin-json-files'], + rules: { + // Prevent having the same package in dependencies and devDependencies. + 'json-files/require-unique-dependency-names': 'error', + + // Require that specific ranges are specified in `package.json` `dependencies`. + 'json-files/restrict-ranges': [ + 'error', + { + versionHint: 'caret', + dependencyTypes: ['dependencies', 'devDependencies'], + }, + ], + + // Require that `engines` are specified in `package.json`. + 'json-files/require-engines': 'error', + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/imports.ts b/packages/eslint-config/src/rule-sets/imports.ts new file mode 100644 index 00000000..8b46c919 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/imports.ts @@ -0,0 +1,86 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Warn about deprecated imports. + 'import/no-deprecated': 'warn', + + // Disallow exporting mutable vars. + 'import/no-mutable-exports': 'error', + + // Disallow AMD modules. + 'import/no-amd': 'error', + + // Disallow mixing ESM with commonjs exports. + 'import/no-import-module-exports': 'error', + + // Disallow importing yourself. + 'import/no-self-import': 'error', + + // Disallow webpack imports. + 'import/no-webpack-loader-syntax': 'error', + + // Ensure imports come first in file. + 'import/first': 'error', + + // Ensure imports are seperated from the rest of the file. + 'import/newline-after-import': 'error', + + // Disallow default exports. + 'import/no-default-export': 'error', + + // Ensure consistent ordering of imports. + 'import/order': [ + 'warn', + { + groups: ['builtin', 'external', 'internal'], + 'newlines-between': 'ignore', + }, + ], + + // Use `import/order` instead. + 'sort-imports': 'off', + + // Disable ES Module import/export. + 'no-restricted-syntax': [ + 'error', + { + selector: 'ImportDeclaration', + message: 'ES Module import not allowed', + }, + { + selector: 'ExportNamedDeclaration', + message: 'ES Module export not allowed', + }, + { + selector: 'ExportDefaultDeclaration', + message: 'ES Module export not allowed', + }, + { + selector: 'ExportAllDeclaration', + message: 'ES Module export not allowed', + }, + { + selector: 'TSExportAssignment', + message: 'ES Module export not allowed', + }, + ], + }, + + overrides: [ + { + files: ['jest.config.*js'], + rules: { + 'import/no-default-export': 'off', + }, + }, + { + files: ['./*.config.js'], + rules: { + 'import/no-commonjs': 'off', + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/miscellaneous.ts b/packages/eslint-config/src/rule-sets/miscellaneous.ts new file mode 100644 index 00000000..be52185d --- /dev/null +++ b/packages/eslint-config/src/rule-sets/miscellaneous.ts @@ -0,0 +1,26 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + /** + * Disallow `console` and `alert` calls. + * Neither of these methods should be used in production. + */ + 'no-console': 'error', + 'no-alert': 'error', + + // Warn about prettier style issues. + 'prettier/prettier': 'warn', + + // Disallow renaming `import`, `export`, and destructured assignments to the same name. + 'no-useless-rename': 'error', + + // Require `symbol`s to have a description. + 'symbol-description': 'error', + + // Require `switch`'s `default` case to be last. + 'default-case-last': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/modern-code.ts b/packages/eslint-config/src/rule-sets/modern-code.ts new file mode 100644 index 00000000..4756280e --- /dev/null +++ b/packages/eslint-config/src/rule-sets/modern-code.ts @@ -0,0 +1,22 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Prefer template literals instead of string concatenation. + 'prefer-template': 'error', + + // Disallow using `.apply()`. + 'prefer-spread': 'error', + + // Prefer a rest parameter instead of `arguments`. + 'prefer-rest-params': 'error', + + // Prefer using arrow functions as callbacks. + 'prefer-arrow-callback': ['error', { allowNamedFunctions: true }], + + // Prefer `const` for vars that are never modified. + 'prefer-const': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/promises.ts b/packages/eslint-config/src/rule-sets/promises.ts new file mode 100644 index 00000000..bcba4313 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/promises.ts @@ -0,0 +1,28 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Require errors from promises are caught. + 'promise/catch-or-return': ['error', { allowThen: true }], + + // Disallow calling resolve multiple times. + 'promise/no-multiple-resolved': 'error', + + // Allow nesting promises. + 'promise/no-nesting': 'off', + + // Allow using promises inside of callbacks. + 'promise/no-promise-in-callback': 'off', + + // Ensure the proper number of arguments are passed to `Promise` functions. + 'promise/valid-params': 'error', + + // Require `async` functions to contain an `await`. + 'require-await': 'error', + + // Prefer using `Promise.all` instead of synchronous loops. + 'no-await-in-loop': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/readability.ts b/packages/eslint-config/src/rule-sets/readability.ts new file mode 100644 index 00000000..0152cce3 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/readability.ts @@ -0,0 +1,49 @@ +import '@rushstack/eslint-patch/modern-module-resolution'; +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Prefer `else if` instead of a lonely `if` inside of an `else`. + 'no-lonely-if': 'error', + + // Require dot notation when possible. + 'dot-notation': 'error', + + // TODO: what should our max be? should we even have one? + // Disallow excessively large files which would be better to be broken up. + 'max-lines': [ + 'error', + { + max: 2000, + skipBlankLines: true, + skipComments: true, + }, + ], + + // Disallow reassigning method params, treating them as `const`. + 'no-param-reassign': 'warn', + + 'no-unused-vars': [ + 'warn', + { + args: 'none', + destructuredArrayIgnorePattern: '^_', + }, + ], + }, + overrides: [ + { + files: '*.json', + plugins: ['eslint-plugin-json-files'], + rules: { + /** + * Require keys in package.json to be sorted, improving readability & + * consistency across projects. + */ + 'json-files/sort-package-json': 'warn', + }, + }, + ], +}; + +export = config; diff --git a/packages/eslint-config/src/rule-sets/security.ts b/packages/eslint-config/src/rule-sets/security.ts new file mode 100644 index 00000000..099e4709 --- /dev/null +++ b/packages/eslint-config/src/rule-sets/security.ts @@ -0,0 +1,11 @@ +import type { ESLint } from 'eslint'; + +const config: ESLint.ConfigData = { + rules: { + // Disallow `eval`. + 'no-eval': 'error', + 'no-implied-eval': 'error', + }, +}; + +export = config; diff --git a/packages/eslint-config/tsconfig.build.json b/packages/eslint-config/tsconfig.build.json new file mode 100644 index 00000000..6b51a225 --- /dev/null +++ b/packages/eslint-config/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src/"], + "exclude": ["**/*.spec.ts"] +} diff --git a/packages/eslint-config/tsconfig.json b/packages/eslint-config/tsconfig.json new file mode 100644 index 00000000..0611a855 --- /dev/null +++ b/packages/eslint-config/tsconfig.json @@ -0,0 +1,14 @@ +// In order to update the this config, update @code-style/typescript-configs +{ + "extends": [ + "@code-style/typescript-configs/roles/node", + "@code-style/typescript-configs/layers/esmodule", + "@code-style/typescript-configs/layers/library" + ], + "compilerOptions": { + "baseUrl": "src/", + "outDir": "dist/" + }, + "include": ["./"], + "exclude": ["dist/", "coverage/"] +} diff --git a/packages/eslint-npm-hoist-packages-esmodule/package.json b/packages/eslint-npm-hoist-packages-esmodule/package.json deleted file mode 100644 index 11feb762..00000000 --- a/packages/eslint-npm-hoist-packages-esmodule/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-esmodule", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages-esmodule/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages-esmodule" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "eslint-plugin-import": "^2.28.1" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - } -} diff --git a/packages/eslint-npm-hoist-packages-jest/package.json b/packages/eslint-npm-hoist-packages-jest/package.json deleted file mode 100644 index 416c5c13..00000000 --- a/packages/eslint-npm-hoist-packages-jest/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-jest", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "eslint-plugin-jest": "^27.4.0" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } - } -} diff --git a/packages/eslint-npm-hoist-packages-nextjs/package.json b/packages/eslint-npm-hoist-packages-nextjs/package.json deleted file mode 100644 index 1392ba06..00000000 --- a/packages/eslint-npm-hoist-packages-nextjs/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-nextjs", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages-nextjs" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "@next/eslint-plugin-next": "^14.1.1" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - } -} diff --git a/packages/eslint-npm-hoist-packages-node/package.json b/packages/eslint-npm-hoist-packages-node/package.json deleted file mode 100644 index c9f22989..00000000 --- a/packages/eslint-npm-hoist-packages-node/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-node", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "eslint-plugin-n": "^17.4.0" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } - } -} diff --git a/packages/eslint-npm-hoist-packages-react/package.json b/packages/eslint-npm-hoist-packages-react/package.json deleted file mode 100644 index 10feb8dd..00000000 --- a/packages/eslint-npm-hoist-packages-react/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-react", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } - } -} diff --git a/packages/eslint-npm-hoist-packages-typescript/package.json b/packages/eslint-npm-hoist-packages-typescript/package.json deleted file mode 100644 index cbc5a030..00000000 --- a/packages/eslint-npm-hoist-packages-typescript/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages-typescript", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", - "eslint-plugin-import": "^2.28.1" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } - } -} diff --git a/packages/eslint-npm-hoist-packages/package.json b/packages/eslint-npm-hoist-packages/package.json deleted file mode 100644 index ade91d6f..00000000 --- a/packages/eslint-npm-hoist-packages/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@code-style/eslint-npm-hoist-packages", - "version": "2.0.0-30", - "description": "Cause NPM to hoist eslint config dependencies", - "keywords": [ - "eslint", - "hack" - ], - "homepage": "https://github.com/dudeofawesome/code-style/blob/main/packages/eslint-npm-hoist-packages/README.md", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/dudeofawesome/code-style.git", - "directory": "/packages/eslint-npm-hoist-packages" - }, - "license": "MIT", - "author": "Louis Orleans ", - "scripts": { - "test": "echo 'No tests'; exit 0" - }, - "dependencies": { - "@eslint-community/eslint-plugin-eslint-comments": "^4.1.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-json-files": "^4.1.0", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-promise": "^6.1.1" - }, - "engines": { - "node": ">=18" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "overrides": { - "eslint-plugin-import": { - "tsconfig-paths": "^4.2.0" - } - } -}