@lzear/eslint-config 4.0.3 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # @lzear/eslint-config
2
+
3
+ [![npm](https://img.shields.io/npm/v/@lzear/eslint-config)](https://www.npmjs.com/package/@lzear/eslint-config)
4
+ [![license](https://img.shields.io/npm/l/@lzear/eslint-config)](../../LICENSE)
5
+
6
+ Shared ESLint flat config for lzear repos. Includes rules for TypeScript, React, Node, Vitest, imports, accessibility, and more.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ npm install -D @lzear/eslint-config eslint
12
+ # or
13
+ yarn add -D @lzear/eslint-config eslint
14
+ ```
15
+
16
+ Requires Node ≥ 20, ESLint ≥ 9.
17
+
18
+ ## Usage
19
+
20
+ **Minimal `eslint.config.ts`:**
21
+
22
+ ```ts
23
+ import lzearConfig from '@lzear/eslint-config'
24
+
25
+ export default await lzearConfig()
26
+ ```
27
+
28
+ **With options** — disable feature sets you don't use:
29
+
30
+ ```ts
31
+ import lzearConfig from '@lzear/eslint-config'
32
+
33
+ export default await lzearConfig({
34
+ react: false, // not a React project
35
+ vitest: false, // no tests
36
+ })
37
+ ```
38
+
39
+ | Option | Default | Description |
40
+ |--------------|---------|------------------------------------------|
41
+ | `typescript` | `true` | TypeScript rules via `typescript-eslint` |
42
+ | `react` | `true` | React, hooks, a11y, compiler rules |
43
+ | `node` | `true` | Node.js rules via `eslint-plugin-n` |
44
+ | `vitest` | `true` | Vitest rules via `@vitest/eslint-plugin` |
45
+
46
+ **Extend with extra rules, overrides, and ignores:**
47
+
48
+ ```ts
49
+ import type { Linter } from 'eslint'
50
+ import lzearConfig from '@lzear/eslint-config'
51
+
52
+ const base = await lzearConfig({ react: false })
53
+
54
+ const config: Linter.Config[] = [
55
+ ...base,
56
+
57
+ // Extra rules applied to all files
58
+ {
59
+ rules: {
60
+ 'no-console': 'error',
61
+ 'unicorn/filename-case': ['error', { case: 'kebabCase' }],
62
+ },
63
+ },
64
+
65
+ // Turn off or downgrade specific rules
66
+ {
67
+ rules: {
68
+ 'sonarjs/cognitive-complexity': 'off',
69
+ 'import-x/order': 'warn',
70
+ },
71
+ },
72
+
73
+ // Override rules for specific files
74
+ {
75
+ files: ['scripts/**/*.ts'],
76
+ rules: {
77
+ 'no-console': 'off',
78
+ 'unicorn/no-process-exit': 'off',
79
+ },
80
+ },
81
+
82
+ // Ignore generated files and specific folders
83
+ {
84
+ ignores: [
85
+ 'src/generated/**',
86
+ 'public/**',
87
+ '**/*.min.js',
88
+ ],
89
+ },
90
+ ]
91
+
92
+ export default config
93
+ ```
94
+
95
+ ## Included plugins
96
+
97
+ `@eslint/js` · `typescript-eslint` · `eslint-plugin-unicorn` · `eslint-plugin-sonarjs` · `eslint-plugin-import-x` · `eslint-plugin-promise` · `eslint-plugin-regexp` · `eslint-plugin-react` · `eslint-plugin-react-hooks` · `eslint-plugin-jsx-a11y` · `eslint-plugin-n` · `@vitest/eslint-plugin` · `eslint-plugin-package-json` · `eslint-config-prettier` · and more.
98
+
99
+ ## Part of forge
100
+
101
+ This package is part of [forge](https://github.com/lzear/forge) — shared dev tooling for lzear repos.
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ interface ConfigOptions {
5
5
  react: boolean;
6
6
  typescript: boolean;
7
7
  vitest: boolean;
8
+ local?: string;
8
9
  }
9
10
  declare const configGenerator: (options?: Partial<ConfigOptions>) => Promise<Linter.Config[]>;
10
11
 
package/dist/index.js CHANGED
@@ -23,11 +23,13 @@ var a11y = (config) => {
23
23
  // configs/core.ts
24
24
  import js from "@eslint/js";
25
25
  import eslintCommentsPlugin from "@eslint-community/eslint-plugin-eslint-comments";
26
+ import stylistic from "@stylistic/eslint-plugin";
26
27
  import deMorganPlugin from "eslint-plugin-de-morgan";
27
28
  import importXPlugin from "eslint-plugin-import-x";
28
29
  import preferArrowPlugin from "eslint-plugin-prefer-arrow";
29
30
  import promisePlugin from "eslint-plugin-promise";
30
31
  import regexpPlugin from "eslint-plugin-regexp";
32
+ import simpleImportSort from "eslint-plugin-simple-import-sort";
31
33
  import sonarjsPlugin from "eslint-plugin-sonarjs";
32
34
  import unicornPlugin from "eslint-plugin-unicorn";
33
35
  import globals from "globals";
@@ -237,7 +239,8 @@ var plugin = {
237
239
  };
238
240
 
239
241
  // configs/core.ts
240
- var core = () => {
242
+ var core = (local) => {
243
+ const l = local?.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`);
241
244
  const files = [
242
245
  "**/*.js",
243
246
  "**/*.cjs",
@@ -254,15 +257,33 @@ var core = () => {
254
257
  ...eslintCommentsPlugin.configs.recommended.rules,
255
258
  "@eslint-community/eslint-comments/disable-enable-pair": 0,
256
259
  "@eslint-community/eslint-comments/no-unlimited-disable": 0,
260
+ ...stylistic.configs.recommended.rules,
261
+ "@stylistic/arrow-parens": 0,
262
+ "@stylistic/brace-style": 0,
263
+ "@stylistic/jsx-self-closing-comp": [2, { component: true, html: true }],
257
264
  ...deMorganPlugin.configs.recommended.rules,
258
265
  ...importXPlugin.configs.recommended.rules,
266
+ "import-x/newline-after-import": 2,
267
+ "import-x/no-duplicates": [2, { "prefer-inline": true }],
268
+ "import-x/no-extraneous-dependencies": 2,
259
269
  "import-x/no-named-as-default-member": 0,
270
+ "import-x/no-relative-packages": 2,
260
271
  "import-x/no-unresolved": 0,
261
- "import-x/order": [
272
+ "import-x/order": 0,
273
+ "simple-import-sort/exports": 2,
274
+ "simple-import-sort/imports": [
262
275
  2,
263
276
  {
264
- alphabetize: { order: "asc", orderImportKind: "asc" },
265
- "newlines-between": "never"
277
+ groups: [
278
+ [
279
+ "^node:",
280
+ l && String.raw`^@?(?!` + l + String.raw`\/)\w`,
281
+ l && String.raw`^@` + l + String.raw`\/`,
282
+ "^",
283
+ String.raw`^\.`,
284
+ String.raw`^.+\.s?css$`
285
+ ].filter(Boolean)
286
+ ]
266
287
  }
267
288
  ],
268
289
  "lzear/prefer-relative-imports": 2,
@@ -277,9 +298,17 @@ var core = () => {
277
298
  ...promisePlugin.configs.recommended.rules,
278
299
  ...regexpPlugin.configs.recommended.rules,
279
300
  ...sonarRules,
301
+ "sonarjs/argument-type": 0,
302
+ // ?
280
303
  "sonarjs/fixme-tag": 0,
304
+ "sonarjs/function-return-type": 0,
305
+ // ?
306
+ "sonarjs/jsx-no-leaked-render": 0,
307
+ // false positives (not checking types)
281
308
  "sonarjs/no-invariant-returns": 0,
282
309
  // annoying
310
+ "sonarjs/no-nested-conditional": 0,
311
+ // unnecessary
283
312
  "sonarjs/no-os-command-from-path": 0,
284
313
  // annoying
285
314
  "sonarjs/os-command": 0,
@@ -310,12 +339,14 @@ var core = () => {
310
339
  },
311
340
  plugins: {
312
341
  "@eslint-community/eslint-comments": eslintCommentsPlugin,
342
+ "@stylistic": stylistic,
313
343
  "de-morgan": deMorganPlugin,
314
344
  "import-x": importXPlugin,
315
345
  lzear: plugin,
316
346
  "prefer-arrow": preferArrowPlugin,
317
347
  promise: promisePlugin,
318
348
  regexp: regexpPlugin,
349
+ "simple-import-sort": simpleImportSort,
319
350
  sonarjs: sonarjsPlugin,
320
351
  unicorn: unicornPlugin
321
352
  },
@@ -435,7 +466,6 @@ var react = async (config) => {
435
466
  reactHooksPlugin,
436
467
  reactPerfPlugin,
437
468
  reactPlugin,
438
- nextPlugin,
439
469
  reactXPlugin,
440
470
  reactDomPlugin,
441
471
  reactWebApiPlugin
@@ -444,7 +474,6 @@ var react = async (config) => {
444
474
  interopDefault(import("eslint-plugin-react-hooks")),
445
475
  interopDefault(import("eslint-plugin-react-perf")),
446
476
  interopDefault(import("eslint-plugin-react")),
447
- interopDefault(import("@next/eslint-plugin-next")),
448
477
  interopDefault(import("eslint-plugin-react-x")),
449
478
  interopDefault(import("eslint-plugin-react-dom")),
450
479
  interopDefault(import("eslint-plugin-react-web-api"))
@@ -457,7 +486,6 @@ var react = async (config) => {
457
486
  name: "lzear/react",
458
487
  files,
459
488
  plugins: {
460
- "@next/next": nextPlugin,
461
489
  react: reactPlugin,
462
490
  "react-compiler": reactCompilerPlugin,
463
491
  "react-dom": reactDomPlugin,
@@ -473,10 +501,8 @@ var react = async (config) => {
473
501
  "react-perf/jsx-no-new-function-as-prop": 0,
474
502
  "react-perf/jsx-no-new-object-as-prop": 0,
475
503
  ...reactPlugin.configs.recommended.rules,
476
- ...nextPlugin.configs.recommended.rules,
477
- ...nextPlugin.configs["core-web-vitals"].rules,
478
504
  "react/react-in-jsx-scope": 0,
479
- "react/no-unknown-property": ["error", { ignore: ["jsx", "global"] }],
505
+ "react/no-unknown-property": [2, { ignore: ["jsx", "global"] }],
480
506
  ...config.typescript ? reactXPlugin.configs["recommended-typescript"].rules : reactXPlugin.configs.recommended.rules,
481
507
  ...reactDomPlugin.configs.recommended.rules,
482
508
  ...reactWebApiPlugin.configs.recommended.rules
@@ -517,6 +543,10 @@ var typescript = async (config) => {
517
543
  ],
518
544
  files,
519
545
  rules: {
546
+ "@typescript-eslint/no-misused-promises": [
547
+ 2,
548
+ { checksVoidReturn: { attributes: false } }
549
+ ],
520
550
  "@typescript-eslint/no-unnecessary-condition": [
521
551
  2,
522
552
  { allowConstantLoopConditions: "only-allowed-literals" }
@@ -607,7 +637,7 @@ var configGenerator = async (options = {}) => {
607
637
  ]);
608
638
  return [
609
639
  { name: "lzear/ignores", ignores },
610
- core(),
640
+ core(config.local),
611
641
  a11y(config),
612
642
  reactConfig,
613
643
  nodeConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzear/eslint-config",
3
- "version": "4.0.3",
3
+ "version": "4.1.1",
4
4
  "description": "Shared ESLint flat config for lzear repos",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  "dependencies": {
30
30
  "@eslint-community/eslint-plugin-eslint-comments": "^4",
31
31
  "@eslint/js": "^9",
32
- "@next/eslint-plugin-next": "^16",
32
+ "@stylistic/eslint-plugin": "^5",
33
33
  "@vitest/eslint-plugin": "^1",
34
34
  "eslint-config-prettier": "^10",
35
35
  "eslint-import-resolver-typescript": "^4",
@@ -37,7 +37,7 @@
37
37
  "eslint-plugin-de-morgan": "^2",
38
38
  "eslint-plugin-import-x": "^4",
39
39
  "eslint-plugin-jsx-a11y": "^6",
40
- "eslint-plugin-n": "^17",
40
+ "eslint-plugin-n": "^18",
41
41
  "eslint-plugin-package-json": "^0.91",
42
42
  "eslint-plugin-prefer-arrow": "^1",
43
43
  "eslint-plugin-prettier": "^5",
@@ -50,6 +50,7 @@
50
50
  "eslint-plugin-react-web-api": "^5",
51
51
  "eslint-plugin-react-x": "^5",
52
52
  "eslint-plugin-regexp": "^3",
53
+ "eslint-plugin-simple-import-sort": "^13",
53
54
  "eslint-plugin-sonarjs": "^4",
54
55
  "eslint-plugin-unicorn": "^64",
55
56
  "globals": "^17",
@@ -58,7 +59,7 @@
58
59
  "typescript-eslint": "^8"
59
60
  },
60
61
  "devDependencies": {
61
- "@lzear/configs": "4.0.3",
62
+ "@lzear/configs": "workspace:*",
62
63
  "@vitest/coverage-v8": "^4",
63
64
  "eslint": "^9",
64
65
  "tsup": "^8",
@@ -74,4 +75,4 @@
74
75
  "publishConfig": {
75
76
  "access": "public"
76
77
  }
77
- }
78
+ }