@moso/eslint-config 2.0.5 → 3.0.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.
Files changed (4) hide show
  1. package/README.md +218 -46
  2. package/dist/index.d.mts +4869 -1579
  3. package/dist/index.mjs +1958 -12662
  4. package/package.json +98 -84
package/README.md CHANGED
@@ -7,14 +7,19 @@ Flat ESLint config for JavaScript, TypeScript, Vue, React, and more.
7
7
  ## Features
8
8
 
9
9
  - [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new) with reasonable but opinionated defaults
10
- - [Stylistic](https://eslint.style) with single quotes, semi enabled, sorted imports, dangling commas,
10
+ - [Stylistic](https://eslint.style) with single quotes, semi enabled, sorted imports, and dangling commas
11
11
  - Aimed to be used without Prettier
12
- - Designed to work with JSX, TypeScript, Vue, and React out of the box
13
- - Applies [Functional](https://github.com/eslint-functional/eslint-plugin-functional) and [Perfectionist](https://perfectionist.dev) by default
14
- - Lints for JSDoc, JSON, RegEx, and YAML
12
+ - Designed to work with JSX, TypeScript, Vue, React, Astro, Nuxt, and Next.js out of the box
13
+ - Applies [Functional](https://github.com/eslint-functional/eslint-plugin-functional), [Perfectionist](https://perfectionist.dev), and [e18e](https://github.com/e18e/eslint-plugin) by default
14
+ - Lints for JSDoc, JSON, RegEx, TOML, and YAML
15
+ - Ships its own small [`@moso`](#custom-rules)-ruleset with security and hygiene rules
15
16
  - Every config can be enabled/disabled
16
17
  - Respects `.gitignore` by default
17
- - Requires ESLint v9.10.0+
18
+ - Requires Node.js >= v22.23.x/v24.18.x, ESLint v10+
19
+
20
+ > [!NOTE]
21
+ > **Note regarding TypeScript v7**
22
+ > See the [FAQ](#typescript-7)
18
23
 
19
24
  ## Configs
20
25
 
@@ -22,7 +27,7 @@ This section contains a list of the plugins used in the named configs that ships
22
27
 
23
28
  \- ✅ Enabled by default
24
29
  \- ☑️ Enabled by auto-detect
25
- \- 🌟 Enabled unless `lessOpinionated: false`
30
+ \- 🌟 Enabled unless `lessOpinionated: true`
26
31
  \- 🟨 Can be enabled manually
27
32
  \- 🎨 Stylistic rules enabled
28
33
  \- 💭 Type-aware rules available by setting the path to your `tsconfig.json`
@@ -39,6 +44,28 @@ This section contains a list of the plugins used in the named configs that ships
39
44
  </thead>
40
45
  <tbody>
41
46
  <tr>
47
+ <td valign="top">
48
+ <details><summary><strong>Astro</strong></summary>
49
+
50
+ [`eslint-plugin-astro`](https://ota-meshi.github.io/eslint-plugin-astro), [`astro-eslint-parser`](https://github.com/ota-meshi/astro-eslint-parser), [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
51
+
52
+ </details></td>
53
+ <td valign="top">☑️ℹ️</td>
54
+ <td valign="top">🎨</td>
55
+ <td valign="top"></td>
56
+ </tr>
57
+ <tr>
58
+ <td valign="top">
59
+ <details><summary><strong>e18e</strong></summary>
60
+
61
+ [`@e18e/eslint-plugin`](https://github.com/e18e/eslint-plugin)
62
+
63
+ </details></td>
64
+ <td valign="top">🌟</td>
65
+ <td valign="top"></td>
66
+ <td valign="top"></td>
67
+ </tr>
68
+ <tr>
42
69
  <td>
43
70
  <details><summary><strong>ESLint Comments</strong></summary>
44
71
 
@@ -57,7 +84,7 @@ This section contains a list of the plugins used in the named configs that ships
57
84
  [`eslint-plugin-functional`](https://github.com/eslint-functional/eslint-plugin-functional)
58
85
 
59
86
  </details></td>
60
- <td valign="top">✅</td>
87
+ <td valign="top">🌟</td>
61
88
  <td valign="top">🎨</td>
62
89
  <td valign="top"></td>
63
90
  </tr>
@@ -107,6 +134,28 @@ This section contains a list of the plugins used in the named configs that ships
107
134
  </tr>
108
135
  <tr>
109
136
  <td valign="top">
137
+ <details><summary><strong>JSX</strong></summary>
138
+
139
+ [`@stylistic/eslint-plugin`](https://eslint.style), [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
140
+
141
+ </details></td>
142
+ <td valign="top">✅ℹ️</td>
143
+ <td valign="top">🎨</td>
144
+ <td valign="top"></td>
145
+ </tr>
146
+ <tr>
147
+ <td valign="top">
148
+ <details><summary><strong>Next.js</strong></summary>
149
+
150
+ [`@next/eslint-plugin-next`](https://nextjs.org/docs/app/api-reference/config/eslint)
151
+
152
+ </details></td>
153
+ <td valign="top">☑️</td>
154
+ <td valign="top"></td>
155
+ <td valign="top"></td>
156
+ </tr>
157
+ <tr>
158
+ <td valign="top">
110
159
  <details><summary><strong>Node</strong></summary>
111
160
 
112
161
  [`eslint-plugin-n`](https://github.com/eslint-community/eslint-plugin-n)
@@ -167,7 +216,7 @@ This section contains a list of the plugins used in the named configs that ships
167
216
  [`@stylistic/eslint-plugin`](https://eslint.style)
168
217
 
169
218
  </details></td>
170
- <td valign="top">🌟</td>
219
+ <td valign="top">✅</td>
171
220
  <td valign="top">🎨</td>
172
221
  <td valign="top"></td>
173
222
  </tr>
@@ -178,12 +227,23 @@ This section contains a list of the plugins used in the named configs that ships
178
227
  [`@vitest/eslint-plugin`](https://github.com/vitest-dev/eslint-plugin-vitest), [`eslint-plugin-no-only-tests`](https://github.com/levibuzolic/eslint-plugin-no-only-tests)
179
228
 
180
229
  </details></td>
181
- <td valign="top">🟨</td>
230
+ <td valign="top">✅</td>
182
231
  <td valign="top"></td>
183
232
  <td valign="top"></td>
184
233
  </tr>
185
234
  <tr>
186
235
  <td valign="top">
236
+ <details><summary><strong>TOML</strong></summary>
237
+
238
+ [`eslint-plugin-toml`](https://ota-meshi.github.io/eslint-plugin-toml)
239
+
240
+ </details></td>
241
+ <td valign="top">✅</td>
242
+ <td valign="top">🎨</td>
243
+ <td valign="top"></td>
244
+ </tr>
245
+ <tr>
246
+ <td valign="top">
187
247
  <details><summary><strong>TypeScript</strong></summary>
188
248
 
189
249
  [`@typescript-eslint`](https://typescript-eslint.io), [`eslint-plugin-erasable-syntax-only`](https://github.com/JoshuaKGoldberg/eslint-plugin-erasable-syntax-only)
@@ -222,17 +282,39 @@ This section contains a list of the plugins used in the named configs that ships
222
282
  [`eslint-plugin-yml`](https://ota-meshi.github.io/eslint-plugin-yml)
223
283
 
224
284
  </details></td>
225
- <td valign="top">🟨</td>
285
+ <td valign="top">✅</td>
226
286
  <td valign="top">🎨</td>
227
287
  <td valign="top"></td>
228
288
  </tr>
229
289
  </tbody>
230
290
  </table>
231
291
 
292
+ ## Custom rules
293
+
294
+ This config ships its own small plugin, registered as `@moso`. Each rule has full documentation next to its implementation.
295
+
296
+ | Rule | Description | Default | Fixable |
297
+ | --- | --- | --- | --- |
298
+ | [`avoid-barrel-files`](./src/rules/avoid-barrel-files/avoid-barrel-files.md) | Disallow *authoring* barrel files | ✅ | |
299
+ | [`no-bidi`](./src/rules/no-bidi/no-bidi.md) | Detect and stop trojan source attacks | ✅ | 🔧 |
300
+ | [`no-force-cast-via-top-type`](./src/rules/no-force-cast-via-top-type/no-force-cast-via-top-type.md) | Disallow `T as any as Q` casts | ✅ | |
301
+ | [`no-import-duplicates`](./src/rules/no-import-duplicates/no-import-duplicates.md) | Fix duplicate specifiers within an import | ✅ | 🔧 |
302
+ | [`no-import-from-dist`](./src/rules/no-import-from-dist/no-import-from-dist.md) | Prevent importing from `dist` folders | ✅ | |
303
+ | [`no-import-node-modules-by-path`](./src/rules/no-import-node-modules-by-path/no-import-node-modules-by-path.md) | Prevent importing `node_modules` by path | ✅ | |
304
+ | [`no-invisible-characters`](./src/rules/no-invisible-characters/no-invisible-characters.md) | Disallow invisible characters | ✅ | 🔧 |
305
+ | [`no-redundant-variable`](./src/rules/no-redundant-variable/no-redundant-variable.md) | Disallow variables that are immediately returned | | 🔧 |
306
+ | [`no-string-interpolation`](./src/rules/no-string-interpolation/no-string-interpolation.md) | Disallow multiline expressions in template literals | | |
307
+ | [`no-top-level-await`](./src/rules/no-top-level-await/no-top-level-await.md) | Prevent top-level `await` | ✅ | |
308
+ | [`no-unneeded-array-flat-map`](./src/rules/no-unneeded-array-flat-map/no-unneeded-array-flat-map.md) | Disallow `flatMap` with identity callbacks | | 🔧 |
309
+ | [`prefer-early-return`](./src/rules/prefer-early-return/prefer-early-return.md) | Prefer guard clauses over wrapped function bodies | | 🔧 |
310
+ | [`prefer-fetch`](./src/rules/prefer-fetch/prefer-fetch.md) | Enforce `fetch` over legacy HTTP clients | | |
311
+ | [`prefer-reduce-over-chaining`](./src/rules/prefer-reduce-over-chaining/prefer-reduce-over-chaining.md) | Prefer one `.reduce()` pass over `.map().filter()` chains | ✅ | |
312
+
232
313
  ## Usage
233
314
 
234
315
  ### Install
235
316
 
317
+ > [!NOTE]
236
318
  > I like to use [Bun](https://bun.sh) because it's hella fast. Thus all the install instructions are with Bun. If you use something else, check the syntax with your favorite package manager.
237
319
 
238
320
  ```bash
@@ -278,8 +360,8 @@ export default moso(
278
360
  // Other flat configs...
279
361
  );
280
362
  ```
281
-
282
- > Note that `.eslintignore` no longer works in Flat config, see [customization](#customization) for more details.
363
+ > [!NOTE]
364
+ > `.eslintignore` no longer works in Flat config, see [customization](#customization) for more details.
283
365
 
284
366
  </details>
285
367
 
@@ -371,15 +453,21 @@ export default moso({
371
453
  // Stylistic rules (enabled by default)
372
454
  stylistic: false, // disable entirely
373
455
  stylistic: {
374
- indent: 2, // 4, or 'tab'
456
+ indent: 4, // 2, or 'tab'
457
+ jsx: true, // or false to disable JSX support
375
458
  quotes: 'single', // or 'double'
459
+ semi: true, // or false
376
460
  },
377
461
 
378
462
  // Auto-detected, or enable explicitly
379
- typescript: true,
463
+ astro: true,
380
464
  react: true,
465
+ typescript: true,
381
466
  vue: true,
382
467
 
468
+ // JSDoc support
469
+ jsdoc: true, // enable explicitly with reasonable defaults
470
+
383
471
  // File format support
384
472
  jsonc: false,
385
473
  yaml: false,
@@ -490,11 +578,68 @@ export default combine(
490
578
 
491
579
  ## Optional configs
492
580
 
581
+ ### JSDoc
582
+
583
+ Disabled by default, will have to be enabled manually.
584
+
585
+ There are many ways JSDoc support can be configured. However, the most simple way is just enabling it which will use very reasonable defaults:
586
+
587
+ ```js
588
+ // eslint.config.js
589
+ import moso from '@moso/eslint-config';
590
+
591
+ export default moso({
592
+ jsdoc: true,
593
+ });
594
+ ```
595
+
596
+ This will enable the preset `recommended`, which is recommended starting rules for enforcing proper tag values, common tags exists, and tags are formatted and styled consistently.
597
+
598
+ Individual rules can be tweaked with the `overrides` property:
599
+
600
+ ```js
601
+ {
602
+ jsdoc: {
603
+ overrides: {
604
+ 'jsdoc/require-description': 'off',
605
+ },
606
+ },
607
+ }
608
+ ```
609
+
610
+ ## Frameworks
611
+
493
612
  Framework support is auto-detected based on installed packages, but can be enabled explicitly. Dependencies are not bundled and will be prompted for installation.
494
613
 
614
+ > [!NOTE]
615
+ > **Note**: Framework support is just as opinionated as the rest of the config. If your favorite framework is missing, then you can always extend the config yourself.
616
+
617
+ ### Astro
618
+
619
+ Auto-detected if you have [Astro](https://astro.build) installed. Enable explicitly:
620
+
621
+ ```js
622
+ // eslint.config.js
623
+ import moso from '@moso/eslint-config';
624
+
625
+ export default moso({
626
+ astro: true,
627
+ });
628
+ ```
629
+
630
+ Install dependencies when prompted, or manually:
631
+
632
+ ```bash
633
+ bun add --dev eslint-plugin-astro astro-eslint-parser
634
+ ```
635
+
636
+ > [!NOTE]
637
+ > Since Astro can be plugged with other frameworks as well, you'll be prompted to install the required packages for linting those as well. Example: If you have installed `@astrojs/react`, you'll be prompted to install the required packages to lint React.
638
+
639
+
495
640
  ### React
496
641
 
497
- Auto-detected if you have Gatsby, Next.js, Nextra, React, or Remix installed. Enable explicitly:
642
+ Auto-detected if you have React, Next.js, Nextra, Remix, Gatsby, or the `@astrojs/react` Astro framework integration installed. Enable explicitly:
498
643
 
499
644
  ```js
500
645
  // eslint.config.js
@@ -513,7 +658,7 @@ bun add --dev @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugi
513
658
 
514
659
  ### Vue
515
660
 
516
- Auto-detected if you have Nuxt, VitePress, or Vue installed. Enable explicitly:
661
+ Auto-detected if you have Vue, Nuxt, VitePress, or the `@astrojs/vue` Astro framework intefration installed. Enable explicitly:
517
662
 
518
663
  ```js
519
664
  // eslint.config.js
@@ -524,13 +669,14 @@ export default moso({
524
669
  });
525
670
  ```
526
671
 
527
- Install dependencies when prompted, or manually:
672
+ Install dependencies when prompted, or manually (the Vue parser and SFC processors are already bundled as dependencies):
528
673
 
529
674
  ```bash
530
- bun add --dev eslint-plugin-vue vue-eslint-parser eslint-processor-vue-blocks eslint-merge-processors
675
+ bun add --dev eslint-plugin-vue
531
676
  ```
532
677
 
533
- **Note**: Since Vue 2 has [reached EOL](https://v2.vuejs.org/eol), this config does not support Vue 2. If you need to support for Vue 2, you'll need to disable the imported configs from Vue 3, and replace them with the Vue 2 ones. You can see an inspiring example on [`eslint-plugin-vue`](https://eslint.vuejs.org/user-guide/#usage). I recommend upgrading to Vue 3 if possible.
678
+ > [!CAUTION]
679
+ > Since Vue 2 has [reached EOL](https://v2.vuejs.org/eol), this config does not support Vue 2. If you need to support for Vue 2, you'll need to disable the imported configs from Vue 3, and replace them with the Vue 2 ones. You can see an inspiring example on [`eslint-plugin-vue`](https://eslint.vuejs.org/user-guide/#usage). I recommend upgrading to Vue 3 if possible.
534
680
 
535
681
  ### Typed Linting
536
682
 
@@ -566,25 +712,26 @@ export default moso(
566
712
 
567
713
  #### Disable type-aware
568
714
 
569
- Optionally, you can even disable type-aware rules on certain file extensions, or even specific files:
715
+ You can disable the type-aware layer entirely, or exclude certain globs or specific files from it:
570
716
 
571
717
  ```js
572
718
  // eslint.config.js
573
719
  import moso from '@moso/eslint-config';
574
720
 
575
- export default moso(
576
- {
577
- projectRoot: import.meta.dirname,
578
- },
579
- {
580
- files: ['**/*.{js,jsx}'],
581
- disableTypeAware: true,
582
- },
583
- {
584
- files: ['**/components/User.jsx'],
585
- disableTypeAware: true,
721
+ export default moso({
722
+ projectRoot: import.meta.dirname,
723
+
724
+ typescript: {
725
+ // Kill switch: keep regular TypeScript rules, drop the type-aware layer
726
+ disableTypeAwareRules: true,
727
+
728
+ // ...or keep it, but exclude globs or specific files from it
729
+ ignoresTypeAware: [
730
+ '**/*.{js,jsx}',
731
+ '**/components/User.tsx',
732
+ ],
586
733
  },
587
- );
734
+ });
588
735
  ```
589
736
 
590
737
  ### Editor specific non-fixes
@@ -593,7 +740,7 @@ Some rules are deemed as 'non-fixable' when inside your editor with ESLint integ
593
740
 
594
741
  - [`prefer-const`](https://eslint.org/docs/rules/prefer-const)
595
742
  - [`unused-imports/no-unused-imports`](https://github.com/sweepline/eslint-plugin-unused-imports)
596
- - [`vitest/no-only-tests`](https://github.com/levibuzolic/eslint-plugin-no-only-tests)
743
+ - [`no-only-tests/no-only-tests`](https://github.com/levibuzolic/eslint-plugin-no-only-tests)
597
744
 
598
745
  Before v1.0.0, they used to be hard disabled. But with a [helper](https://github.com/antfu/eslint-flat-config-utils#composerdisablerulesfix), they are now just marked as 'non-fixable'. They are re-applied when you're linting through a terminal, or by using [Lint Staged](#lint-staged).
599
746
 
@@ -615,7 +762,7 @@ Linting and auto-fixing before every commit is easy, you just add the following
615
762
  "simple-git-hooks": {
616
763
  "pre-commit": "bunx lint-staged"
617
764
  },
618
- "lint-staged": {
765
+ "nano-staged": {
619
766
  "*": "eslint --fix"
620
767
  }
621
768
  }
@@ -624,23 +771,42 @@ Linting and auto-fixing before every commit is easy, you just add the following
624
771
  and then
625
772
 
626
773
  ```bash
627
- bun add -dev lint-staged simple-git-hooks
774
+ bun add --dev nano-staged simple-git-hooks
628
775
 
629
776
  # to activate the hooks
630
777
  bunx simple-git-hooks
631
778
  ```
632
779
 
633
- ## View which rules are enabled
780
+ ## FAQ
781
+
782
+ ### ESLint v9, older Node.js versions?
783
+
784
+ ESLint v9 will reach [EOL on August 6th, 2026](https://eslint.org/version-support). The world of development moves fast, and as with Vue v2.x, I don't intend to support versions that has reached EOL unless absolutely necessary. The same goes with older Node.js versions.
785
+
786
+ Even though ESLint v10 supports Node.js `v20.19.0` (as of current status), this version has also reached EOL. The rest of their requirements mention `v22.13.0` and `>= 24`. However, the minimum requirements of some of the configs that this sharable config apply rules from have a minimum requirement of `v22.22.3`, this project will stay within this range.
634
787
 
635
- [Antfu](https://github.com/antfu) built a visual tool that can help you view what rules are enabled in your project: [@eslint/config-inspector](https://github.com/eslint/config-inspector).
788
+ ### TypeScript 7?
636
789
 
637
- To view it in action, navigate to the root of your project that contains your `eslint.config.js` and run:
790
+ TypeScript 7.0 [does not ship a compiler API](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/) (a new one supposedly arrives in 7.1), so [`typescript-eslint`](https://typescript-eslint.io) - and therefore all TypeScript linting in this config - cannot run against it. TypeScript's supported setup is running TypeScript 6 side-by-side through the [`@typescript/typescript6`](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0) compatibility package, aliased so tooling that imports `typescript` keeps working:
638
791
 
639
792
  ```bash
640
- bunx @eslint/config-inspector
793
+ bun add --dev typescript@npm:@typescript/typescript6
641
794
  ```
642
795
 
643
- ## FAQ
796
+ Optionally keep TypeScript 7's own `tsc` around as well:
797
+
798
+ ```jsonc
799
+ {
800
+ "devDependencies": {
801
+ "@typescript/native": "npm:typescript@^7.0.2",
802
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
803
+ }
804
+ }
805
+ ```
806
+
807
+ With the alias in place, this config works unchanged. Without it, the config detects TypeScript >7 and fails fast: an explicit `typescript: true` throws with these instructions, while auto-detection prints a warning and degrades to JavaScript-only linting instead of crashing inside the parser.
808
+
809
+ **Keep in mind**, this is temporary until an API is provided by TypeScript for v7.
644
810
 
645
811
  ### I want it less opinionated
646
812
 
@@ -660,10 +826,16 @@ export default moso({
660
826
 
661
827
  ```js
662
828
  {
663
- functional: true, // will default to 'lite' enforcement
829
+ // Disable opinionated rules
830
+ lessOpinionated: true,
664
831
 
665
- // Optionally change the `functionalEnforcement`:
666
- functionalEnforcement: 'recommended',
832
+ // Re-enable functional - a string sets the enforcement level directly
833
+ functional: 'lite', // 'lite' | 'recommended' | 'strict'
834
+
835
+ // ...or as an object:
836
+ functional: {
837
+ functionalEnforcement: 'recommended',
838
+ },
667
839
 
668
840
  // Re-enable `perfectionist`
669
841
  perfectionist: true,
@@ -672,7 +844,7 @@ export default moso({
672
844
 
673
845
  ### Prettier? dprint?
674
846
 
675
- You can still use these to format files that aren't linted with this config, however, I strongly recommend you only format your code with ESLint, as Pretter and other AST-reading-then-reprint projects tend to ignore stuff like the original line breaks and might also cause inconsistent diffs when commiting code.
847
+ You can still use these to format files that aren't linted with this config, however, I strongly recommend you only format your code with ESLint, as Prettier and other AST-reading-then-reprint projects tend to ignore stuff like the original line breaks and might also cause inconsistent diffs when committing code.
676
848
 
677
849
  ### How to format CSS?
678
850
 
@@ -705,8 +877,8 @@ A personal thank-you to Anthony, Rebecca, Sukka, and Azat, and everyone else who
705
877
  - Simplification in some areas
706
878
  - Better type-aware checks
707
879
  - Plugin memoization
708
- - Optional a11y support for React and Vue
709
- - No dangerous plugin renaming
880
+ - Optional a11y support for JSX, React and Vue
881
+ - No dangerous plugin renaming (except for `node`)
710
882
 
711
883
  ## License
712
884