This commit is contained in:
Alex 2025-02-26 14:00:41 -05:00
parent cddee19340
commit d7990e5cf1
11 changed files with 1296 additions and 1199 deletions

28
dist/package.json vendored
View File

@ -1,6 +1,6 @@
{
"name": "@aet/eslint-rules",
"version": "2.0.36",
"version": "2.0.41",
"license": "UNLICENSED",
"type": "module",
"bin": {
@ -23,18 +23,18 @@
"@tanstack/eslint-plugin-query": "^5.62.1"
},
"dependencies": {
"@aet/eslint-define-config": "^0.1.7",
"@aet/eslint-define-config": "^0.1.9",
"@antfu/install-pkg": "^1.0.0",
"@eslint-community/eslint-utils": "^4.4.1",
"@eslint-react/eslint-plugin": "1.26.1",
"@eslint/js": "^9.19.0",
"@eslint-react/eslint-plugin": "1.28.0",
"@eslint/js": "^9.21.0",
"@nolyfill/is-core-module": "^1.0.39",
"@stylistic/eslint-plugin": "^3.0.1",
"@stylistic/eslint-plugin": "^4.1.0",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.23.0",
"@typescript-eslint/parser": "^8.23.0",
"@typescript-eslint/type-utils": "^8.23.0",
"@typescript-eslint/utils": "^8.23.0",
"@typescript-eslint/eslint-plugin": "^8.25.0",
"@typescript-eslint/parser": "^8.25.0",
"@typescript-eslint/type-utils": "^8.25.0",
"@typescript-eslint/utils": "^8.25.0",
"aria-query": "^5.3.2",
"axe-core": "^4.10.2",
"axobject-query": "4.1.0",
@ -43,18 +43,18 @@
"doctrine": "^3.0.0",
"emoji-regex": "^10.4.0",
"enhanced-resolve": "^5.18.1",
"eslint-config-prettier": "^10.0.1",
"eslint-config-prettier": "^10.0.2",
"eslint-import-resolver-node": "^0.3.9",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-import-resolver-typescript": "^3.8.3",
"eslint-module-utils": "^2.12.0",
"eslint-plugin-import-x": "^4.6.1",
"eslint-plugin-unicorn": "^56.0.1",
"eslint-plugin-unicorn": "^57.0.0",
"esprima": "^4.0.1",
"esquery": "^1.6.0",
"estraverse": "^5.3.0",
"fast-glob": "^3.3.3",
"get-tsconfig": "^4.10.0",
"globals": "^15.14.0",
"globals": "^16.0.0",
"ignore": "^7.0.3",
"is-bun-module": "^1.3.0",
"is-glob": "^4.0.3",
@ -62,7 +62,7 @@
"lodash-es": "^4.17.21",
"minimatch": "^10.0.1",
"semver": "^7.7.1",
"typescript-eslint": "^8.23.0"
"typescript-eslint": "^8.25.0"
},
"pnpm": {
"overrides": {

View File

@ -11,18 +11,18 @@
},
"private": true,
"dependencies": {
"@aet/eslint-define-config": "^0.1.7",
"@aet/eslint-define-config": "^0.1.9",
"@antfu/install-pkg": "^1.0.0",
"@eslint-community/eslint-utils": "^4.4.1",
"@eslint-react/eslint-plugin": "1.26.1",
"@eslint/js": "^9.19.0",
"@eslint-react/eslint-plugin": "1.28.0",
"@eslint/js": "^9.21.0",
"@nolyfill/is-core-module": "^1.0.39",
"@stylistic/eslint-plugin": "^3.0.1",
"@stylistic/eslint-plugin": "^4.1.0",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.23.0",
"@typescript-eslint/parser": "^8.23.0",
"@typescript-eslint/type-utils": "^8.23.0",
"@typescript-eslint/utils": "^8.23.0",
"@typescript-eslint/eslint-plugin": "^8.25.0",
"@typescript-eslint/parser": "^8.25.0",
"@typescript-eslint/type-utils": "^8.25.0",
"@typescript-eslint/utils": "^8.25.0",
"aria-query": "^5.3.2",
"axe-core": "^4.10.2",
"axobject-query": "4.1.0",
@ -31,18 +31,19 @@
"doctrine": "^3.0.0",
"emoji-regex": "^10.4.0",
"enhanced-resolve": "^5.18.1",
"eslint-config-prettier": "^10.0.1",
"eslint-config-prettier": "^10.0.2",
"eslint-import-resolver-node": "^0.3.9",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-import-resolver-typescript": "^3.8.3",
"eslint-module-utils": "^2.12.0",
"eslint-plugin-import-x": "^4.6.1",
"eslint-plugin-unicorn": "^56.0.1",
"eslint-plugin-regexp": "^2.7.0",
"eslint-plugin-unicorn": "^57.0.0",
"esprima": "^4.0.1",
"esquery": "^1.6.0",
"estraverse": "^5.3.0",
"fast-glob": "^3.3.3",
"get-tsconfig": "^4.10.0",
"globals": "^15.14.0",
"globals": "^16.0.0",
"ignore": "^7.0.3",
"is-bun-module": "^1.3.0",
"is-glob": "^4.0.3",
@ -50,38 +51,37 @@
"lodash-es": "^4.17.21",
"minimatch": "^10.0.1",
"semver": "^7.7.1",
"typescript-eslint": "^8.23.0"
"typescript-eslint": "^8.25.0"
},
"devDependencies": {
"@babel/core": "^7.26.7",
"@babel/core": "^7.26.9",
"@babel/plugin-transform-flow-strip-types": "^7.26.5",
"@babel/preset-env": "^7.26.7",
"@babel/preset-env": "^7.26.9",
"@graphql-eslint/eslint-plugin": "^4.3.0",
"@swc-node/register": "^1.10.9",
"@tanstack/eslint-plugin-query": "^5.66.0",
"@tanstack/eslint-plugin-query": "^5.66.1",
"@types/babel-plugin-macros": "^3.1.3",
"@types/babel__core": "^7.20.5",
"@types/eslint-config-prettier": "^6.11.3",
"@types/eslint-plugin-tailwindcss": "^3.17.0",
"@types/eslint__js": "^8.42.3",
"@types/esprima": "^4.0.6",
"@types/esquery": "^1.5.4",
"@types/estree": "^1.0.6",
"@types/estree-jsx": "^1.0.5",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.13.1",
"@types/node": "^22.13.5",
"@types/react-refresh": "^0.14.6",
"@typescript-eslint/types": "^8.23.0",
"@typescript-eslint/typescript-estree": "^8.23.0",
"@vitest/eslint-plugin": "^1.1.25",
"@typescript-eslint/types": "^8.25.0",
"@typescript-eslint/typescript-estree": "^8.25.0",
"@vitest/eslint-plugin": "^1.1.34",
"babel-plugin-macros": "^3.1.0",
"dts-bundle-generator": "9.5.1",
"esbuild": "0.24.2",
"esbuild": "0.25.0",
"esbuild-plugin-alias": "^0.2.1",
"eslint": "^9.19.0",
"eslint": "^9.21.0",
"eslint-plugin-jsdoc": "^50.6.3",
"eslint-plugin-react-refresh": "^0.4.18",
"eslint-plugin-storybook": "^0.11.2",
"eslint-plugin-react-refresh": "^0.4.19",
"eslint-plugin-storybook": "^0.11.3",
"eslint-plugin-testing-library": "^7.1.1",
"find-cache-dir": "^5.0.0",
"graphql": "^16.10.0",
@ -89,10 +89,10 @@
"nolyfill": "^1.0.43",
"patch-package": "^8.0.0",
"picocolors": "^1.1.1",
"prettier": "^3.4.2",
"prettier": "^3.5.2",
"prop-types": "^15.8.1",
"terser": "^5.38.0",
"type-fest": "^4.33.0",
"terser": "^5.39.0",
"type-fest": "^4.35.0",
"typescript": "^5.7.3"
},
"prettier": {

@ -1 +0,0 @@
Subproject commit 3dfad602a05b4b3812a4d3fc681051932f86e838

@ -1 +1 @@
Subproject commit 5943318eaf23764eec3ff397ebb969613d728a95
Subproject commit a8ca8f70331b02db537b0b5cf72ea10e3d6c9377

2286
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@
"subject": "[patch] `no-autofocus`: don't report error if autoFocus is set to false"
},
"eslint-plugin-n": {
"hash": "4efe60f37c71ce3d71932714207bac780332cf3d",
"date": "2025-02-01T12:40:03+01:00",
"hash": "17a60cd1abc8d70be6674f97521e8e98d5a415d1",
"date": "2025-02-23T11:50:33+08:00",
"committer": "GitHub",
"subject": "perf: improve `prefer-node-protocol`'s performance (#406)"
"subject": "chore(master): release 17.16.0 (#402)"
},
"eslint-plugin-react": {
"hash": "983b88dd3cb5e07919517d3fde4085f60883ded7",
@ -24,9 +24,9 @@
"subject": "[Tests] `no-array-index-key`: actually run valid tests"
},
"jsx-ast-utils": {
"hash": "5943318eaf23764eec3ff397ebb969613d728a95",
"date": "2023-07-28T18:34:04-07:00",
"hash": "a8ca8f70331b02db537b0b5cf72ea10e3d6c9377",
"date": "2025-02-20T08:51:06-08:00",
"committer": "Jordan Harband",
"subject": "v3.3.5"
"subject": "[Dev Deps] pin `psl` due to breaking change in a minor version"
}
}

View File

@ -3,6 +3,7 @@ import type { ESLint } from 'eslint';
import noEmptyObjectLiteral from './no-empty-object-literal';
import noImportDot from './no-import-dot';
import noUselessImportAlias from './no-useless-import-alias';
import requireImportAttribute from './require-import-attribute';
import restrictTemplateExpressions from './restrict-template-expressions';
type RuleLevel = 'error' | 'warn' | 'off' | 0 | 1 | 2;
@ -10,29 +11,32 @@ type RuleEntry<Options> = RuleLevel | [RuleLevel, Partial<Options>];
export interface LocalRuleOptions {
/** Bans import from the specifier '.' and '..' and replaces it with '.+/index' */
'custom/no-import-dot': RuleEntry<unknown>;
'aet/no-import-dot': RuleEntry<unknown>;
/**
* Enforce template literal expressions to be of `string` type
* @see [restrict-template-expressions](https://typescript-eslint.io/rules/restrict-template-expressions)
*/
'typed-custom/restrict-template-expressions': RuleEntry<{ allow: string[] }>;
'typed-aet/restrict-template-expressions': RuleEntry<{ allow: string[] }>;
/** Ban assignment of empty object literals `{}` and replace them with `Object.create(null)` */
'custom/no-empty-object-literal': RuleEntry<unknown>;
'aet/no-empty-object-literal': RuleEntry<unknown>;
/** Ban useless import alias */
'custom/no-useless-import-alias': RuleEntry<unknown>;
'aet/no-useless-import-alias': RuleEntry<unknown>;
/** Require the use of `{ type: "json" }` for JSON imports. */
'aet/require-import-attribute': RuleEntry<unknown>;
}
export const plugin: ESLint.Plugin = {
name: 'custom',
name: 'aet',
rules: {
'no-empty-object-literal': noEmptyObjectLiteral,
'no-import-dot': noImportDot,
'no-useless-import-alias': noUselessImportAlias,
'require-import-attribute': requireImportAttribute,
},
};
export const typedPlugin: ESLint.Plugin = {
name: 'typed-custom',
name: 'typed-aet',
rules: {
// @ts-expect-error type mismatch
'restrict-template-expressions': restrictTemplateExpressions,

View File

@ -0,0 +1,61 @@
import type { Rule } from 'eslint';
import type { Identifier, SimpleLiteral } from 'estree';
interface ImportAttribute {
key: Identifier | SimpleLiteral;
value: SimpleLiteral;
}
const requireImportAttribute: Rule.RuleModule = {
meta: {
type: 'problem',
docs: {
description:
'Requires JSON imports to have a "with { type: \'json\' }" import attribute.',
category: 'Possible Errors',
recommended: false,
},
fixable: 'code',
schema: [],
messages: {
missingJsonTypeAttribute:
'JSON imports must have a "with { type: \'json\' }" import attribute.',
},
},
create(context) {
return {
ImportDeclaration(node) {
// Only check modules that end with ".json"
if (
typeof node.source.value === 'string' &&
node.source.value.endsWith('.json')
) {
// Cast the node to our extended interface to access the assertions.
const importNode = node;
const assertions = (
importNode as {
assertions?: ImportAttribute[];
}
).assertions;
const hasJsonType = assertions?.some(attr => {
const keyName =
(attr.key as Identifier).name ?? (attr.key as SimpleLiteral).value;
return keyName === 'type' && attr.value.value === 'json';
});
if (!hasJsonType) {
context.report({
node,
messageId: 'missingJsonTypeAttribute',
fix: fixer =>
fixer.insertTextAfterRange(node.source.range!, ' with { type: "json" }'),
});
}
}
},
};
},
};
export default requireImportAttribute;

View File

@ -1,9 +1,11 @@
/* eslint-disable import-x/no-named-as-default-member */
import fs from 'node:fs';
import type { FlatESLintConfig } from '@aet/eslint-define-config';
import * as tsParser from '@typescript-eslint/parser';
import prettier from 'eslint-config-prettier';
import importPlugin from 'eslint-plugin-import-x';
import * as regexpPlugin from 'eslint-plugin-regexp';
import { uniq } from 'lodash-es';
import tseslint from 'typescript-eslint';
@ -72,6 +74,7 @@ export async function extendConfig(
importPlugin.flatConfigs.typescript,
...unicorn,
stylistic,
regexpPlugin.configs['flat/recommended'],
{
name: 'eslint-rules/typescript-and-import-x',
files: ['**/*.{js,mjs,cjs,jsx,ts,tsx,mts,cts}'],

View File

@ -4,20 +4,21 @@ import { defineConfig } from '../types';
export default defineConfig([
{
name: 'eslint-rules/custom',
plugins: { custom: plugin },
name: 'eslint-rules/aet',
plugins: { aet: plugin },
rules: {
'custom/no-import-dot': error,
'custom/no-useless-import-alias': error,
'aet/no-import-dot': error,
'aet/no-useless-import-alias': error,
'aet/require-import-attribute': error,
} satisfies Partial<LocalRuleOptions>,
},
{
name: 'eslint-rules/typed-custom',
plugins: { 'typed-custom': typedPlugin },
name: 'eslint-rules/typed-aet',
plugins: { 'typed-aet': typedPlugin },
files: ['**/*.ts'],
ignores: ['**/*.d.ts'],
rules: {
'typed-custom/restrict-template-expressions': error,
'typed-aet/restrict-template-expressions': error,
} satisfies Partial<LocalRuleOptions>,
},
]);

View File

@ -13,5 +13,18 @@ export async function reactQuery() {
export async function vitest() {
const { configs } = def(await import('@vitest/eslint-plugin'));
return defineConfig([configs.recommended]);
return defineConfig([
configs.recommended,
{
rules: {
'vitest/expect-expect': [
'error',
{
assertFunctionNames: ['expect*'],
additionalTestBlockFunctions: ['describe*'],
},
],
},
},
]);
}