Skip to content

Commit

Permalink
Merge branch 'release/v2.0.0-alpha.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
andreashuber69 committed Dec 26, 2024
2 parents 2232ce9 + ec6c0bc commit 99f1ee3
Show file tree
Hide file tree
Showing 14 changed files with 2,810 additions and 2,464 deletions.
10 changes: 0 additions & 10 deletions .eslintrc.cjs

This file was deleted.

14 changes: 14 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import generalConfig from "./index.js";

const config = [
{
files: ["**/*.ts"],
},
{
ignores: ["coverage/"],
},
...generalConfig,
];

// eslint-disable-next-line import/no-default-export
export default config;
1,651 changes: 843 additions & 808 deletions index.js

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions languageOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import tsParser from "@typescript-eslint/parser";
import globals from "globals";

export const languageOptions = {
globals: {
...globals.node,
},
parser: tsParser,
parserOptions: {
// As of typescript-eslint v8.18.0, it is not entirely clear how projectService should be configured.
// Many examples specify allowDefaultProject: ["*.js"], but that does not work here.
projectService: {
allowDefaultProject: ["eslint.config.js"],
defaultProject: "./tsconfig.json",
},
tsconfigRootDir: process.cwd(),
},
};
3,369 changes: 1,803 additions & 1,566 deletions package-lock.json

Large diffs are not rendered by default.

60 changes: 38 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@andreashuber69/eslint-config",
"version": "1.2.32",
"version": "2.0.0-alpha.0",
"description": "Provides a comprehensive, carefullly curated and tested shareable eslint config for TypeScript projects.",
"keywords": [
"eslint",
Expand All @@ -20,7 +20,7 @@
"author": {
"name": "Andreas Huber"
},
"main": "index.js",
"type": "module",
"files": [
"/index.js",
"/*.md"
Expand All @@ -30,49 +30,65 @@
},
"scripts": {
"prelint": "cspell '**' && markdownlint '**/*.md'",
"lint": "eslint --ext .cjs,.js,.ts --report-unused-disable-directives '.'",
"lint": "eslint --report-unused-disable-directives '.'",
"test-no-coverage": "node --import tsx --test test/*.spec.ts",
"test": "c8 --exclude 'test/**' --reporter=text --reporter=lcov npm run test-no-coverage",
"show-coverage": "vite 'coverage/lcov-report' --logLevel error --open",
"ci": "npm run lint && tsc && npm test",
"finish-release": "git push && git push --tags"
"preversion": "git checkout develop && git push && git pull",
"version": "git flow release start v`cat package.json | jq -r '.version' && git stash push >/dev/null 2>&1` && git stash pop",
"postversion": "git commit -a -m \"chore: start release v`cat package.json | jq -r '.version'`\"",
"finish-release": "git flow release finish -p -m \"chore: finish release\" v`cat package.json | jq -r '.version'`"
},
"peerDependencies": {
"@stylistic/eslint-plugin": "^2.11.0",
"@typescript-eslint/eslint-plugin": "^8.17.0",
"@typescript-eslint/parser": "^8.17.0",
"eslint": "^8.57.1",
"@eslint/compat": "^1.2.4",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.16.0",
"@stylistic/eslint-plugin": "^2.12.1",
"@types/eslint": "^9.6.1",
"@types/eslint__eslintrc": "^2.1.2",
"@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^8.18.2",
"eslint": "^9.17.0",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.0",
"eslint-plugin-jsdoc": "^50.6.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-unicorn": "^56.0.1"
"eslint-plugin-unicorn": "^56.0.1",
"globals": "^15.14.0",
"typescript-eslint": "^8.18.2"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^2.11.0",
"@eslint/compat": "^1.2.4",
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.16.0",
"@stylistic/eslint-plugin": "^2.12.1",
"@tsconfig/node-lts": "^22.0.1",
"@tsconfig/strictest": "^2.0.5",
"@types/eslint": "^8.56.12",
"@types/eslint": "^9.6.1",
"@types/eslint__eslintrc": "^2.1.2",
"@types/node-fetch": "^2.6.12",
"@typescript-eslint/eslint-plugin": "8.17.0",
"@typescript-eslint/parser": "8.17.0",
"c8": "^10.1.2",
"@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^8.18.2",
"c8": "^10.1.3",
"coveralls": "^3.1.1",
"cspell": "^8.16.1",
"eslint": "^8.57.1",
"cspell": "^8.17.1",
"eslint": "^9.17.0",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "50.6.0",
"eslint-plugin-promise": "7.2.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-jsdoc": "^50.6.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "5.1.0",
"eslint-plugin-unicorn": "^56.0.1",
"globals": "^15.14.0",
"markdownlint-cli": "^0.43.0",
"node-fetch": "^2.7.0",
"tsx": "^4.19.2",
"typescript": "^5.7.2",
"vite": "^6.0.3"
"typescript-eslint": "^8.18.2",
"vite": "^6.0.5"
}
}
4 changes: 2 additions & 2 deletions test/allJsdocRules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// https://github.com/andreashuber69/eslint-config/blob/master/README.md#----andreashuber69eslint-config

import { rules } from "eslint-plugin-jsdoc";
import jsdoc from "eslint-plugin-jsdoc";
import { getSeverities } from "./getSeverities.js";

export const allJsdocRules = getSeverities(rules, "jsdoc");
export const allJsdocRules = getSeverities(jsdoc.rules, "jsdoc");
4 changes: 2 additions & 2 deletions test/allPromiseRules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// https://github.com/andreashuber69/eslint-config/blob/master/README.md#----andreashuber69eslint-config

import { rules } from "eslint-plugin-promise";
import promise from "eslint-plugin-promise";
import { getSeverities } from "./getSeverities.js";

export const allPromiseRules = getSeverities(rules, "promise");
export const allPromiseRules = getSeverities(promise.rules, "promise");
6 changes: 0 additions & 6 deletions test/eslintPluginJsdoc.d.ts

This file was deleted.

6 changes: 5 additions & 1 deletion test/eslintPluginPromise.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@

// eslint-disable-next-line import/unambiguous
declare module "eslint-plugin-promise" {
export const rules: unknown;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const index = { rules: unknown };

// eslint-disable-next-line import/no-default-export
export default index;
}
9 changes: 9 additions & 0 deletions test/getRuleSeverities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// https://github.com/andreashuber69/eslint-config/blob/master/README.md#----andreashuber69eslint-config

import { getRules } from "./getRules.js";
import { getSeverities } from "./getSeverities.js";

export const getRuleSeverities = async (config?: unknown[]) =>
// eslint-disable-next-line no-warning-comments
// TODO: Possibly superfluous?
Object.fromEntries(Object.entries(getSeverities(await getRules(config))));
47 changes: 23 additions & 24 deletions test/getRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,32 @@

import type { Linter } from "eslint";
import { ESLint } from "eslint";
import { getSeverities } from "./getSeverities.js";
import { languageOptions } from "../languageOptions.js";

export const getRules = async (config?: Linter.Config) => {
const options = {
useEslintrc: false,
overrideConfig: {
env: {
es2024: true,
node: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
ecmaVersion: "latest" as const,
sourceType: "module" as const,
},
plugins: [
"@typescript-eslint",
"@stylistic",
"unicorn",
],
...config,
},
const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null;

export const getRules = async (config?: unknown[]): Promise<Record<string, unknown>> => {
const options: ESLint.Options = {
overrideConfigFile: true,
overrideConfig: [
// There's no other way
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
...((config ?? []) as Linter.Config[]),
{ languageOptions },
],
};

const eslint = new ESLint(config ? options : undefined);
const fullConfig = (await eslint.calculateConfigForFile("index.js")) as unknown;
const rules = fullConfig && typeof fullConfig === "object" && "rules" in fullConfig ? fullConfig.rules : undefined;
return Object.fromEntries(Object.entries(getSeverities(rules)));

if (fullConfig && typeof fullConfig === "object" && "rules" in fullConfig) {
const { rules } = fullConfig;

if (isRecord(rules)) {
return rules;
}
}

throw new Error("Unexpected config!");
};
74 changes: 53 additions & 21 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,28 @@ import assert from "node:assert";
import { describe, it } from "node:test";
import { isDeepStrictEqual } from "node:util";

import { rules as ourTypedChanges } from "../index.js";
import type { FixupPluginDefinition } from "@eslint/compat";
import { fixupPluginRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import stylistic from "@stylistic/eslint-plugin";
import importPlugin from "eslint-plugin-import";
import jsdoc from "eslint-plugin-jsdoc";
import promise from "eslint-plugin-promise";
import reactHooks from "eslint-plugin-react-hooks";
import unicorn from "eslint-plugin-unicorn";
import tsEslint from "typescript-eslint";

import ourTypedChanges from "../index.js";

import { allImportRules } from "./allImportRules.js";
import { allJsdocRules } from "./allJsdocRules.js";
import { allPromiseRules } from "./allPromiseRules.js";
import { allReactHooksRules } from "./allReactHooksRules.js";
import { getRules } from "./getRules.js";
import { getRuleSeverities } from "./getRuleSeverities.js";

const ourChanges = ourTypedChanges as Record<string, unknown>;
const ourChanges = await getRules(ourTypedChanges);

const compare = (a: string, b: string) => {
// Sort rules without prefix before rules with prefix
Expand All @@ -37,16 +50,26 @@ const sort = (rules: Record<string, unknown>) => {
return Object.entries(rules).sort(strippedCompare);
};

const getAllConfigsRules = async () => await getRules({
extends: [
"eslint:all",
"plugin:@typescript-eslint/all",
"plugin:react/all",
"plugin:@stylistic/disable-legacy",
"plugin:@stylistic/all-extends",
"plugin:unicorn/all",
],
});
const getAllConfigsRules = async () => await getRuleSeverities([
js.configs.all,
// eslint-disable-next-line import/no-named-as-default-member
...tsEslint.configs.all,
...new FlatCompat().extends("plugin:react/all"),
stylistic.configs["disable-legacy"],
stylistic.configs["all-flat"],
unicorn.configs["flat/all"],
{
plugins: {
// "@stylistic": stylistic,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
import: fixupPluginRules(importPlugin as FixupPluginDefinition),
jsdoc,
promise,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
"react-hooks": fixupPluginRules(reactHooks as FixupPluginDefinition),
},
},
]);

const allOtherRules = { ...allImportRules, ...allJsdocRules, ...allPromiseRules, ...allReactHooksRules };

Expand Down Expand Up @@ -85,17 +108,20 @@ getAllConfigsRules().then(async (allConfigsRules) => {
"@stylistic/jsx-curly-spacing",
"@stylistic/jsx-equals-spacing",
"@stylistic/jsx-first-prop-new-line",
"@stylistic/jsx-function-call-newline",
"@stylistic/jsx-indent",
"@stylistic/jsx-indent-props",
"@stylistic/jsx-max-props-per-line",
"@stylistic/jsx-newline",
"@stylistic/jsx-one-expression-per-line",
"@stylistic/jsx-pascal-case",
"@stylistic/jsx-props-no-multi-spaces",
"@stylistic/jsx-quotes",
"@stylistic/jsx-self-closing-comp",
"@stylistic/jsx-sort-props",
"@stylistic/jsx-tag-spacing",
"@stylistic/jsx-wrap-multilines",
"@stylistic/line-comment-position",
"@stylistic/max-len",
"@stylistic/max-statements-per-line",
"@stylistic/no-mixed-operators",
Expand Down Expand Up @@ -172,7 +198,7 @@ getAllConfigsRules().then(async (allConfigsRules) => {


const rulesToTest = Object.fromEntries(
Object.entries(await getRules()).filter(([i, s]) => s !== "off" && !exceptions.has(i)),
Object.entries(await getRuleSeverities()).filter(([i, s]) => s !== "off" && !exceptions.has(i)),
);

const lookup = new Map<string, string>();
Expand All @@ -193,19 +219,25 @@ getAllConfigsRules().then(async (allConfigsRules) => {
const getRuleCount = (rules: Record<string, unknown>) => Object.entries(rules).filter(([_, s]) => s !== "off").length;

const showStats = async () => {
const recommendedCount = getRuleCount(await getRules({
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
],
}));
const recommendedCount = getRuleCount(await getRuleSeverities([
js.configs.recommended,
// eslint-disable-next-line import/no-named-as-default-member
...tsEslint.configs.recommended,
...new FlatCompat().extends("plugin:react/recommended"),
{
plugins: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
"react-hooks": fixupPluginRules(reactHooks as FixupPluginDefinition),
},
},
]));

console.log(`eslint, @typescript-eslint & eslint-plugin-react recommended active rules: ${recommendedCount}`);
const ourCount = getRuleCount(await getRules());
const ourCount = getRuleCount(await getRuleSeverities());
console.log(`@andreashuber/eslint-config active rules: ${ourCount}`);
};

// FIX
// This is a CommonJS module, where top-level await is not available. Compiling tests differently is possible but not
// worth the effort.
// eslint-disable-next-line unicorn/prefer-top-level-await
Expand Down
2 changes: 0 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
"noEmit": true
},
"include": [
".eslintrc.cjs",
"index.js",
"test/**/*.ts"
]
}

0 comments on commit 99f1ee3

Please sign in to comment.