Skip to content

Commit 260ce39

Browse files
committed
feat: more work on the configs
Signed-off-by: prisis <[email protected]>
1 parent f166a11 commit 260ce39

19 files changed

+15447
-24130
lines changed

packages/eslint-config/.prettierrc.cjs

-5
This file was deleted.

packages/eslint-config/.prettierrc.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
import config from "@anolilab/prettier-config";
3+
4+
export default {
5+
...config,
6+
};
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// eslint-disable-next-line import/extensions
12
import { createConfig } from "./dist";
23

34
export default createConfig({});

packages/eslint-config/eslint.config.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ import { createConfig } from "./dist/index.mjs";
22

33
export default createConfig(
44
{
5-
ignores: ["eslint.config.js", "typegen.d.ts"],
5+
ignores: ["eslint.config.js", "src/typegen.d.ts"],
66
},
77
{
88
files: ["**/*.ts"],
99
rules: {
1010
"no-secrets/no-secrets": "off",
1111
},
1212
},
13+
{
14+
files: ["debug-eslint.config.mjs"],
15+
rules: {
16+
"antfu/no-import-dist": "off"
17+
}
18+
}
1319
);

packages/eslint-config/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,10 @@
104104
"dist"
105105
],
106106
"scripts": {
107-
"build": "packem build --development",
108-
"build:prod": "packem build --production",
107+
"build": "pnpm run build:typegen && pnpm run build:global-vitest && packem build --development",
108+
"build:prod": "pnpm run build:typegen && pnpm run build:global-vitest && packem build --production",
109109
"build:typegen": "tsx ./scripts/typegen.ts",
110+
"build:global-vitest": "tsx ./scripts/global-vitest.ts",
110111
"clean": "rimraf node_modules dist",
111112
"debug:rules": "pnpm exec eslint-config-inspector --config ./debug-eslint.config.mjs",
112113
"lint:attw": "attw --pack",

packages/eslint-config/scripts/global-vitest.ts

+34-21
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,38 @@ import { createRequire } from "node:module";
33
import { dirname, join } from "node:path";
44
import { fileURLToPath } from "node:url";
55

6+
import type { ModuleBody, SourceFile } from "typescript";
67
// eslint-disable-next-line import/no-extraneous-dependencies
78
import ts from "typescript";
89

9-
const __dirname = dirname(fileURLToPath(import.meta.url));
10+
const rootPath = dirname(fileURLToPath(import.meta.url));
1011

11-
const e = (message, fail = true) => {
12+
const showMessageAndExit = (message: string, fail = true) => {
1213
// eslint-disable-next-line no-console
1314
console.log(message);
1415

16+
// eslint-disable-next-line unicorn/no-process-exit
1517
process.exit(fail ? 1 : 0);
1618
};
1719

18-
function extract(file) {
20+
const extract = (file: string) => {
1921
const program = ts.createProgram([file], {});
20-
const sourceFile = program.getSourceFile(file);
21-
const globals = [];
22+
const sourceFile = program.getSourceFile(file) as SourceFile;
23+
const globals: string[] = [];
2224

2325
ts.forEachChild(sourceFile, (node) => {
2426
if (ts.isModuleDeclaration(node)) {
25-
ts.forEachChild(node.body, (node) => {
26-
if (ts.isVariableStatement(node)) {
27-
ts.forEachChild(node, (node) => {
28-
if (ts.isVariableDeclarationList(node)) {
29-
for (const declaration of node.declarations) {
27+
ts.forEachChild(node.body as ModuleBody, (mNode) => {
28+
if (ts.isVariableStatement(mNode)) {
29+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
30+
ts.forEachChild(mNode, (vNode: any) => {
31+
if (ts.isVariableDeclarationList(vNode)) {
32+
// eslint-disable-next-line no-restricted-syntax
33+
for (const declaration of vNode.declarations) {
3034
const name = ts.getNameOfDeclaration(declaration);
3135

32-
if (name) {
33-
globals.push(name.escapedText);
36+
if (name && "escapedText" in name) {
37+
globals.push(name.escapedText as string);
3438
}
3539
}
3640
}
@@ -41,32 +45,41 @@ function extract(file) {
4145
});
4246

4347
return globals;
44-
}
48+
};
4549

4650
const require = createRequire(import.meta.url);
4751
const packagePath = require.resolve("vitest/package.json");
52+
4853
const {
4954
default: { version: vitestVersion },
5055
} = await import(packagePath, {
5156
with: { type: "json" },
5257
});
5358

5459
if (!vitestVersion) {
55-
e("Vitest version cannot be read.");
60+
showMessageAndExit("Vitest version cannot be read.");
5661
}
5762

58-
writeFileSync(join(__dirname, "..", "VERSION"), vitestVersion);
59-
6063
const globalsPath = require.resolve("vitest/globals.d.ts");
64+
6165
const globalsArray = extract(globalsPath);
62-
const globals = {};
66+
const globals: Record<string, boolean> = {};
67+
68+
if (globalsArray.length === 0) {
69+
showMessageAndExit("No globals! Check extractor implementation.");
70+
}
6371

64-
if (globalsArray.length === 0) e("No globals! Check extractor implementation.");
72+
globalsArray.forEach((globalName) => {
73+
globals[globalName] = true;
74+
});
6575

66-
globalsArray.forEach(globalName => (globals[globalName] = true));
67-
const moduleContent = `export default /** @type {const} */ (${JSON.stringify(globals, undefined, 2)});`;
76+
const moduleContent = `/**
77+
* vitest version ${vitestVersion}
78+
*/
79+
export default /** @type {const} */ (${JSON.stringify(globals, undefined, 4)});
80+
`;
6881

69-
writeFileSync(join(__dirname, "..", "index.mjs"), moduleContent);
82+
writeFileSync(join(rootPath, "..", "src", "utils", "vitest-globals.ts"), moduleContent);
7083

7184
// eslint-disable-next-line no-console
7285
console.log("Finished generation with result:\n", moduleContent);

packages/eslint-config/src/config/best-practices.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,7 @@ export default createConfig<OptionsFiles>("all", async (config, oFiles) => {
451451
// https://eslint.org/docs/rules/no-void
452452
"no-void": "error",
453453

454-
// eslint-disable-next-line sonarjs/todo-tag
455-
// disallow usage of configurable warning terms in comments: e.g. todo
454+
// disallow usage of configurable warning terms in comments: e.g. "todo"
456455
"no-warning-comments": [
457456
"off",
458457
{

packages/eslint-config/src/config/plugins/formatters.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,13 @@ const formatters = async (options: OptionsFormatters, stylistic: StylisticConfig
177177
if (options.markdown) {
178178
const formater = options.markdown === true ? "prettier" : options.markdown;
179179

180-
const GLOB_SLIDEV = options.slidev ? options.slidev === true ? ["**/slides.md"] : options.slidev.files : [];
180+
let GLOB_SLIDEV: string[] = [];
181+
182+
if (typeof options.slidev === "boolean" && options.slidev === true) {
183+
GLOB_SLIDEV = ["**/slides.md"];
184+
} else if (typeof options.slidev === "object" && options.slidev.files) {
185+
GLOB_SLIDEV = options.slidev.files;
186+
}
181187

182188
configs.push({
183189
files: getFilesGlobs("markdown"),

packages/eslint-config/src/config/plugins/imports.ts

+20-15
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,27 @@ export default createConfig<OptionsCwd & OptionsFiles & OptionsOverrides & Optio
6868
"import/extensions": [
6969
"error",
7070
"ignorePackages",
71-
packageJson.type === "module"
72-
? {
73-
cjs: "always",
74-
js: "always",
75-
json: "always",
76-
jsx: "always",
77-
mjs: "always",
78-
}
79-
: {
80-
cjs: "never",
81-
js: "never",
82-
json: "always",
83-
jsx: "never",
84-
mjs: "never",
71+
{
72+
checkTypeImports: tsconfigPath !== undefined,
73+
ignorePackages: true,
74+
pattern: {
75+
...packageJson.type === "module"
76+
? {
77+
cjs: "always",
78+
js: "always",
79+
json: "always",
80+
jsx: "always",
81+
mjs: "always",
82+
}
83+
: {
84+
cjs: "never",
85+
js: "never",
86+
json: "always",
87+
jsx: "never",
88+
mjs: "never",
89+
},
8590
},
91+
},
8692
],
8793

8894
// disallow non-import statements appearing before import statements
@@ -286,7 +292,6 @@ export default createConfig<OptionsCwd & OptionsFiles & OptionsOverrides & Optio
286292
// https://github.com/import-js/eslint-plugin-import/blob/44a038c06487964394b1e15b64f3bd34e5d40cde/docs/rules/no-self-import.md
287293
"import/no-self-import": "error",
288294

289-
// eslint-disable-next-line sonarjs/todo-tag
290295
// @TODO: Enable this rule when it's fixed https://github.com/import-js/eslint-plugin-import/issues/2678
291296
// Reports modules without any exports, or with unused exports
292297
// https://github.com/import-js/eslint-plugin-import/blob/f63dd261809de6883b13b6b5b960e6d7f42a7813/docs/rules/no-unused-modules.md

packages/eslint-config/src/config/plugins/jsonc.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { hasPackageJsonAnyDependency } from "@visulima/package";
2+
import type { Linter } from "eslint";
23

34
import type {
45
OptionsHasPrettier,
@@ -27,6 +28,7 @@ const jsonc = async (
2728
const hasSortPackageJson = hasPackageJsonAnyDependency(packageJson, ["sort-package-json"]);
2829

2930
if (hasSortPackageJson && !silent) {
31+
// eslint-disable-next-line no-console
3032
console.info(`\n@anolilab/eslint-config found "sort-package-json" package. \n
3133
Following rules are disabled: jsonc/sort-keys for all package.json files. \n`);
3234
}
@@ -36,23 +38,17 @@ const jsonc = async (
3638
{
3739
files: ["**/*.json5"],
3840
name: "anolilab/jsonc/json5-rules",
39-
rules: {
40-
...jsoncPlugin.configs["flat/recommended-with-json5"].rules,
41-
},
41+
rules: (jsoncPlugin.configs["recommended-with-json5"] as Linter.Config).rules,
4242
},
4343
{
4444
files: ["**/*.jsonc"],
4545
name: "anolilab/jsonc/jsonc-rules",
46-
rules: {
47-
...jsoncPlugin.configs["flat/recommended-with-jsonc"].rules,
48-
},
46+
rules: (jsoncPlugin.configs["recommended-with-jsonc"] as Linter.Config).rules,
4947
},
5048
{
5149
files: ["**/*.json"],
5250
name: "anolilab/jsonc/json-rules",
53-
rules: {
54-
...jsoncPlugin.configs["flat/recommended-with-json"].rules,
55-
},
51+
rules: (jsoncPlugin.configs["recommended-with-json"] as Linter.Config).rules,
5652
},
5753
{
5854
files: ["**/package.json"],

packages/eslint-config/src/config/plugins/markdown.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default createConfig<OptionsComponentExtensions & OptionsFiles & OptionsO
2424
// `eslint-plugin-markdown` only creates virtual files for code blocks,
2525
// but not the markdown file itself. We use `eslint-merge-processors` to
2626
// add a pass-through processor for the markdown file itself.
27-
processor: mergeProcessors([markdown.processors!.markdown, processorPassThrough]),
27+
processor: mergeProcessors([markdown.processors?.markdown, processorPassThrough]),
2828
},
2929
{
3030
files,

packages/eslint-config/src/config/plugins/sonarjs.ts

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export default createConfig<OptionsFiles & OptionsOverrides>("all", async (confi
2525
"sonarjs/no-nested-template-literals": "off",
2626
"sonarjs/no-tab": "error",
2727

28+
// This rule does not work will with disable next line
29+
"sonarjs/todo-tag": "off",
30+
2831
...overrides,
2932
},
3033
},

packages/eslint-config/src/config/plugins/vitest.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import type {
77
} from "../../types";
88
import { createConfig } from "../../utils/create-config";
99
import interopDefault from "../../utils/interop-default";
10+
import vitestGlobals from "../../utils/vitest-globals";
1011

1112
// Hold the reference so we don't redeclare the plugin on each call
1213
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1314
let pluginTest: any;
1415

1516
export default createConfig<OptionsFiles & OptionsHasPrettier & OptionsIsInEditor & OptionsOverrides & OptionsTypeScriptWithTypes>(
16-
"all",
17+
"vitest",
1718
async (config, oFiles) => {
1819
const {
1920
files = oFiles,
@@ -57,7 +58,11 @@ export default createConfig<OptionsFiles & OptionsHasPrettier & OptionsIsInEdito
5758
},
5859
}
5960
: {},
60-
61+
languageOptions: {
62+
globals: {
63+
...vitestGlobals,
64+
},
65+
},
6166
name: "anolilab/vitest/rules",
6267
rules: {
6368
...vitestPlugin.configs.all.rules,

packages/eslint-config/src/index.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,22 @@ import type {
6060
} from "./types";
6161
import { getFilesGlobs } from "./utils/create-config";
6262
import interopDefault from "./utils/interop-default";
63-
import isInEditorEnvironment from "./utils/is-in-editor";
63+
import isInEditorEnvironment from "./utils/is-in-editor-environment";
6464

6565
const flatConfigProperties = ["name", "languageOptions", "linterOptions", "processor", "plugins", "rules", "settings"] satisfies (keyof TypedFlatConfigItem)[];
6666

6767
export type ResolvedOptions<T> = T extends boolean ? never : NonNullable<T>;
6868

6969
export const resolveSubOptions = <K extends keyof OptionsConfig>(options: OptionsConfig, key: K): ResolvedOptions<OptionsConfig[K]> => {
70+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7071
return typeof options[key] === "boolean" ? ({} as any) : options[key] || {};
7172
};
7273

7374
export const getOverrides = <K extends keyof OptionsConfig>(options: OptionsConfig, key: K): Partial<Linter.RulesRecord & RuleOptions> => {
7475
const sub = resolveSubOptions(options, key);
7576

7677
return {
78+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7779
...(options.overrides as any)?.[key],
7880
..."overrides" in sub ? sub.overrides : {},
7981
};
@@ -105,6 +107,7 @@ export const getFiles = <K extends keyof OptionsConfig>(options: OptionsConfig,
105107
*/
106108
export const createConfig = async (
107109
options: Omit<TypedFlatConfigItem, "files"> & OptionsConfig = {},
110+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
108111
...userConfigs: Awaitable<FlatConfigComposer<any, any> | Linter.Config[] | TypedFlatConfigItem | TypedFlatConfigItem[]>[]
109112
// eslint-disable-next-line sonarjs/cognitive-complexity
110113
): Promise<FlatConfigComposer<TypedFlatConfigItem, ConfigNames>> => {
@@ -921,6 +924,7 @@ export const createConfig = async (
921924
// eslint-disable-next-line unicorn/no-array-reduce
922925
const fusedConfig = flatConfigProperties.reduce((accumulator, key) => {
923926
if (key in options) {
927+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
924928
accumulator[key] = options[key] as any;
925929
}
926930

@@ -933,6 +937,7 @@ export const createConfig = async (
933937

934938
let composer = new FlatConfigComposer<TypedFlatConfigItem, ConfigNames>();
935939

940+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
936941
composer = composer.append(...configs, ...(userConfigs as any));
937942

938943
return composer;

0 commit comments

Comments
 (0)