This commit is contained in:
David Arranz 2025-05-02 13:22:10 +02:00
parent d169b78c00
commit 16522afca4
10 changed files with 338 additions and 178 deletions

View File

@ -1,3 +0,0 @@
# `@turbo/eslint-config`
Collection of internal eslint configurations.

View File

@ -0,0 +1,115 @@
import { fixupPluginRules } from "@eslint/compat";
import eslint from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import _import from "eslint-plugin-import";
import perfectionist from "eslint-plugin-perfectionist";
import prettier from "eslint-plugin-prettier";
import globals from "globals";
import tseslint from "typescript-eslint";
import flatCompat from "./compat.js";
const tsConfig = /** @type {import("eslint").Linter.Config[]} */ (tseslint.configs.strict);
/** @type {import("eslint").Linter.Config[]} */
export default [
eslint.configs.recommended,
...tsConfig,
eslintConfigPrettier.rules,
perfectionist.configs["recommended-natural"],
...flatCompat.plugins("eslint-plugin-only-warn"),
{
languageOptions: {
globals: {
...globals.node,
JSX: true,
React: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
},
plugins: {
"@typescript-eslint": tseslint.plugin,
import: fixupPluginRules(_import),
prettier,
},
},
{
ignores: [
".*.?(c)js",
"*.config*.?(c)js",
".*.ts",
"*.config*.ts",
"*.d.ts",
"dist",
".git",
"node_modules",
"build",
".next",
"*rollup*",
],
},
{
rules: {
"@typescript-eslint/consistent-type-imports": [
"warn",
{
fixStyle: "inline-type-imports",
prefer: "type-imports",
},
],
"@typescript-eslint/naming-convention": [
"warn",
{
format: ["PascalCase"],
selector: "typeLike",
},
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
"arrow-body-style": "off",
"import/no-anonymous-default-export": "off",
"no-duplicate-imports": "error",
"no-unused-vars": "off",
"perfectionist/sort-objects": [
"error",
{
type: "alphabetical",
},
],
"prefer-arrow-callback": "off",
"prettier/prettier": [
"error",
{
endOfLine: "lf",
printWidth: 80,
semi: true,
singleQuote: false,
tabWidth: 2,
trailingComma: "all",
},
],
},
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
"import/resolver": {
node: {
extensions: [".js", ".jsx", ".ts", ".tsx"],
},
typescript: {
alwaysTryTypes: true,
project: ["./tsconfig.json"],
},
},
},
},
];

View File

@ -0,0 +1,13 @@
import { FlatCompat } from "@eslint/eslintrc";
import path from "path";
import { fileURLToPath } from "url";
// mimic CommonJS variables -- not needed if using CommonJS
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname, // optional; default: process.cwd()
});
export default compat;

View File

@ -0,0 +1,75 @@
import globals from "globals";
import tseslint from "typescript-eslint";
import baseConfig from "./base.js";
/** @type {import("eslint").Linter.Config[]} */
export default [
...baseConfig,
{
languageOptions: {
globals: {
...globals.node,
Express: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
},
plugins: {
"@typescript-eslint": tseslint.plugin,
},
rules: {
"@typescript-eslint/consistent-type-imports": [
"warn",
{
fixStyle: "inline-type-imports",
prefer: "type-imports",
},
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-floating-promises": ["error", { ignoreVoid: true }],
// TypeScript specific rules
"@typescript-eslint/no-misused-promises": [
"error",
{
checksVoidReturn: false,
},
],
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
},
],
"@typescript-eslint/require-await": "off",
"import/no-default-export": "off",
"import/prefer-default-export": "off",
// Express and Node specific rules
"no-console": ["warn", { allow: ["warn", "error"] }],
"no-process-env": "off",
// Error handling
"no-unused-vars": "error",
},
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts"],
},
"import/resolver": {
node: {
extensions: [".js", ".ts"],
},
typescript: {
alwaysTryTypes: true,
project: ["./tsconfig.json"],
},
},
},
},
];

View File

@ -1,34 +0,0 @@
const { resolve } = require("node:path");
const project = resolve(process.cwd(), "tsconfig.json");
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ["eslint:recommended", "prettier", "turbo"],
plugins: ["only-warn"],
globals: {
React: true,
JSX: true,
},
env: {
node: true,
},
settings: {
"import/resolver": {
typescript: {
project,
},
},
},
ignorePatterns: [
// Ignore dotfiles
".*.js",
"node_modules/",
"dist/",
],
overrides: [
{
files: ["*.js?(x)", "*.ts?(x)"],
},
],
};

View File

@ -0,0 +1,81 @@
import { fixupConfigRules } from "@eslint/compat";
import next from "@next/eslint-plugin-next";
import globals from "globals";
import tseslint from "typescript-eslint";
import baseConfig from "./base.js";
import flatCompat from "./compat.js";
const nextConfig = /** @type {import("eslint").Linter.Config[]} */ (
fixupConfigRules(
/** @type {import("@eslint/compat").FixupConfigArray} */
(flatCompat.config(next.configs["core-web-vitals"]))
)
);
/** @type {import("eslint").Linter.Config[]} */
export default [
...baseConfig,
...nextConfig,
{
languageOptions: {
globals: {
...globals.node,
...globals.browser,
JSX: true,
React: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
},
plugins: {
"@typescript-eslint": tseslint.plugin,
next,
},
rules: {
// Next.js specific rules
"@next/next/no-html-link-for-pages": "off",
"@next/next/no-img-element": "off",
// TypeScript specific rules
"@typescript-eslint/array-type": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/consistent-type-imports": [
"warn",
{
fixStyle: "inline-type-imports",
prefer: "type-imports",
},
],
"@typescript-eslint/no-empty-function": "off",
// Import/Export rules
"import/no-default-export": "off",
"import/prefer-default-export": "off",
"react/display-name": "off",
"react/prop-types": "off",
// React specific rules
"react/react-in-jsx-scope": "off",
},
settings: {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
"import/resolver": {
node: {
extensions: [".js", ".jsx", ".ts", ".tsx"],
},
typescript: {
alwaysTryTypes: true,
project: ["./tsconfig.json"],
},
},
react: {
version: "detect",
},
},
},
];

View File

@ -1,20 +1,35 @@
{
"name": "@repo/eslint-config",
"version": "0.0.0",
"version": "0.0.1",
"private": true,
"main": "./base.js",
"type": "module",
"exports": {
"./base": "./base.js",
"./next": "./next.js",
"./express": "./express.js",
"./react-internal": "./react-internal.js"
},
"files": [
"library.js",
"react-internal.js",
"server.js",
"vite.js"
"next.js",
"express.js",
"base.js",
"react-internal.js"
],
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.31.0",
"@typescript-eslint/parser": "^8.31.0",
"eslint-config-prettier": "^10.1.2",
"eslint-config-turbo": "^2.5.2",
"@eslint/js": "^9.24.0",
"@eslint/compat": "^1.2.8",
"@eslint/eslintrc": "^3.3.1",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
"globals": "^16.0.0",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-security": "^3.0.1",
"eslint-config-prettier": "^10.1.1",
"@next/eslint-plugin-next": "^15.2.4",
"eslint-plugin-perfectionist": "^4.11.0",
"eslint-plugin-only-warn": "^1.1.0",
"typescript": "5.8.3"
"typescript-eslint": "^8.29.0"
}
}

View File

@ -1,39 +1,34 @@
const { resolve } = require("node:path");
import globals from "globals";
import tseslint from "typescript-eslint";
const project = resolve(process.cwd(), "tsconfig.json");
import baseConfig from "./base.js";
/*
* This is a custom ESLint configuration for use with
* internal (bundled by their consumer) libraries
* that utilize React.
*/
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ["eslint:recommended", "prettier", "turbo"],
plugins: ["only-warn"],
globals: {
React: true,
JSX: true,
},
env: {
browser: true,
},
settings: {
"import/resolver": {
typescript: {
project,
/** @type {import("eslint").Linter.Config[]} */
export default [
...baseConfig,
{
languageOptions: {
globals: {
...globals.browser,
JSX: true,
React: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
},
plugins: {
"@typescript-eslint": tseslint.plugin,
},
rules: {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
},
settings: {
react: {
version: "detect",
},
},
},
ignorePatterns: [
// Ignore dotfiles
".*.js",
"node_modules/",
"dist/",
],
overrides: [
// Force ESLint to detect .tsx files
{ files: ["*.js?(x)", "*.ts?(x)"] },
],
};
];

View File

@ -1,78 +0,0 @@
const { rules } = require("eslint-config-prettier");
module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "sort-class-members"],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
env: {
browser: false,
node: true,
es6: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
overrides: [
{
files: ["**/__tests__/**/*"],
env: {
jest: true,
},
},
],
rules: {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/recommended-requiring-type-checking": "off",
"@typescript-eslint/no-unused-vars": "warn",
"lines-between-class-members": ["error", "always", { exceptAfterSingleLine: true }],
"sort-class-members/sort-class-members": [
2,
{
order: [
"[static-properties]",
"[static-methods]",
"[conventional-private-properties]",
"[properties]",
"constructor",
"[methods]",
"[conventional-private-methods]",
],
accessorPairPositioning: "getThenSet",
},
],
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^T$" },
],
"import/no-relative-parent-imports": "error",
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", ["parent", "sibling", "index"]],
pathGroups: [
{
pattern: "@/**",
group: "internal",
},
],
pathGroupsExcludedImportTypes: ["builtin"],
"newlines-between": "always",
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
settings: {
"import/resolver": {
typescript: {
project,
},
},
},
};

View File

@ -1,19 +0,0 @@
module.exports = {
env: {
node: true,
},
parser: "@typescript-eslint/parser",
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
plugins: ["@typescript-eslint"],
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
},
};