@fabdeh/eslint-config 0.1.2 → 0.2.0

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/dist/index.mjs CHANGED
@@ -1,19 +1,20 @@
1
+ import { isPackageExists } from 'local-pkg';
1
2
  import tseslint from 'typescript-eslint';
2
3
  import { statSync } from 'node:fs';
3
- import { dirname, join } from 'node:path';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { resolve, dirname, join } from 'node:path';
4
6
  import process from 'node:process';
5
7
  import { fileURLToPath } from 'node:url';
6
- import { isPackageExists } from 'local-pkg';
7
- import eslintComments from '@eslint-community/eslint-plugin-eslint-comments';
8
- import * as importX from 'eslint-plugin-import-x';
9
8
  import eslint from '@eslint/js';
10
9
  import preferArrowFunctions from 'eslint-plugin-prefer-arrow-functions';
11
10
  import unusedImports from 'eslint-plugin-unused-imports';
12
11
  import globals from 'globals';
12
+ import eslintComments from '@eslint-community/eslint-plugin-eslint-comments';
13
+ import * as importX from 'eslint-plugin-import-x';
13
14
  import jsdocPlugin from 'eslint-plugin-jsdoc';
14
- import { mergeProcessors, processorPassThrough } from 'eslint-merge-processors';
15
15
  import perfectionistPlugin from 'eslint-plugin-perfectionist';
16
16
  import unicornPlugin from 'eslint-plugin-unicorn';
17
+ import { mergeProcessors, processorPassThrough } from 'eslint-merge-processors';
17
18
 
18
19
  const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
19
20
  const GLOB_SRC = `**/*.${GLOB_SRC_EXT}`;
@@ -75,24 +76,6 @@ const GLOB_EXCLUDE = [
75
76
 
76
77
  const SCOPE_URL = fileURLToPath(new URL(".", import.meta.url));
77
78
  const IS_CWD_IN_SCOPE = isPackageExists("@fabdeh/eslint-config");
78
- function isInEditorEnv() {
79
- if (process.env.CI) {
80
- return false;
81
- }
82
- const envKeys = Object.keys(process.env);
83
- if (envKeys.some((k) => /^GIT_/i.test(k))) {
84
- return false;
85
- }
86
- const isVsCode = envKeys.some((k) => /^VSCODE_/i.test(k));
87
- const isIntelliJ = envKeys.some((k) => /^INTELLIJ_/i.test(k));
88
- const isJetbrains = envKeys.some((k) => /^JETBRAINS_/i.test(k));
89
- const isVim = envKeys.some((k) => /^VIM$/i.test(k));
90
- const isNeoVim = envKeys.some((k) => /^NVIM$/i.test(k));
91
- return isVsCode || isIntelliJ || isJetbrains || isVim || isNeoVim;
92
- }
93
- function toArray(value) {
94
- return Array.isArray(value) ? value : [value];
95
- }
96
79
  async function interopDefault(m) {
97
80
  const resolved = await m;
98
81
  return resolved.default ?? resolved;
@@ -139,6 +122,19 @@ async function ensurePackages(packages) {
139
122
  await import('@antfu/install-pkg').then((i) => i.installPackage(nonExistingPackages, { dev: true }));
140
123
  }
141
124
  }
125
+ async function findNearestPackageJsonName(directoryPath = resolve()) {
126
+ try {
127
+ const packageJsonPath = join(directoryPath, "package.json");
128
+ const packageJsonData = JSON.parse(await readFile(packageJsonPath, "utf8"));
129
+ return packageJsonData.name;
130
+ } catch {
131
+ const parentDir = dirname(directoryPath);
132
+ if (directoryPath === parentDir) {
133
+ throw new Error("No package.json file found.");
134
+ }
135
+ return findNearestPackageJsonName(parentDir);
136
+ }
137
+ }
142
138
 
143
139
  async function angular(options = {}) {
144
140
  const angularEslint = await interopDefault(import('angular-eslint'));
@@ -151,10 +147,36 @@ async function angular(options = {}) {
151
147
  },
152
148
  processor: angularEslint.processInlineTemplates,
153
149
  files: [GLOB_TS],
154
- extends: [angularEslint.configs.tsRecommended],
155
150
  rules: {
156
151
  "max-classes-per-file": ["error", 1],
157
152
  "max-lines": ["error", 400],
153
+ "new-cap": [
154
+ "error",
155
+ {
156
+ capIsNewExceptions: [
157
+ "Attribute",
158
+ "Component",
159
+ "ContentChild",
160
+ "ContentChildren",
161
+ "Directive",
162
+ "Host",
163
+ "HostBinding",
164
+ "HostListener",
165
+ "Inject",
166
+ "Injectable",
167
+ "Input",
168
+ "NgModule",
169
+ "Optional",
170
+ "Output",
171
+ "Pipe",
172
+ "Self",
173
+ "SkipSelf",
174
+ "ViewChild",
175
+ "ViewChildren"
176
+ ]
177
+ }
178
+ ],
179
+ ...angularEslint.configs.tsRecommended.find((c) => c.name === "angular-eslint/ts-recommended")?.rules,
158
180
  "@angular-eslint/component-max-inline-declarations": "error",
159
181
  "@angular-eslint/component-selector": [
160
182
  "error",
@@ -194,14 +216,14 @@ async function angular(options = {}) {
194
216
  {
195
217
  name: "fabdeh/angular-template/rules",
196
218
  plugins: {
197
- "@angular-eslint": angularEslint.tsPlugin
219
+ "@angular-eslint/template": angularEslint.templatePlugin
220
+ },
221
+ languageOptions: {
222
+ parser: angularEslint.templateParser
198
223
  },
199
224
  files: [GLOB_HTML],
200
- extends: [
201
- ...angularEslint.configs.templateRecommended,
202
- ...enableAccessibilityRules ? angularEslint.configs.templateAccessibility : []
203
- ],
204
225
  rules: {
226
+ ...angularEslint.configs.templateRecommended.find((c) => c.name === "angular-eslint/template-recommended")?.rules,
205
227
  "@angular-eslint/template/attributes-order": ["error", { alphabetical: true }],
206
228
  "@angular-eslint/template/button-has-type": "error",
207
229
  "@angular-eslint/template/conditional-complexity": "error",
@@ -213,6 +235,8 @@ async function angular(options = {}) {
213
235
  "@angular-eslint/template/prefer-control-flow": "error",
214
236
  "@angular-eslint/template/prefer-ngsrc": "error",
215
237
  "@angular-eslint/template/prefer-self-closing-tags": "error",
238
+ "@angular-eslint/template/prefer-static-string-properties": "error",
239
+ ...enableAccessibilityRules ? angularEslint.configs.templateAccessibility.find((c) => c.name === "angular-eslint/template-accessibility")?.rules : {},
216
240
  ...htmlOverrides
217
241
  }
218
242
  }
@@ -294,7 +318,7 @@ function imports(options = {}) {
294
318
  }
295
319
 
296
320
  function javascript(options = {}) {
297
- const { isInEditor = false, overrides = {}, allowAngularDecorator = false } = options;
321
+ const { overrides = {} } = options;
298
322
  return tseslint.config(
299
323
  {
300
324
  name: "fabdeh/javascript/setup",
@@ -330,8 +354,8 @@ function javascript(options = {}) {
330
354
  "prefer-arrow-functions": preferArrowFunctions,
331
355
  "unused-imports": unusedImports
332
356
  },
333
- extends: [eslint.configs.recommended, ...tseslint.configs.recommended],
334
357
  rules: {
358
+ ...eslint.configs.recommended.rules,
335
359
  "accessor-pairs": "error",
336
360
  "array-callback-return": "error",
337
361
  "block-scoped-var": "error",
@@ -350,32 +374,7 @@ function javascript(options = {}) {
350
374
  "Undefined",
351
375
  "undefined"
352
376
  ],
353
- "new-cap": allowAngularDecorator ? [
354
- "error",
355
- {
356
- capIsNewExceptions: [
357
- "Attribute",
358
- "Component",
359
- "ContentChild",
360
- "ContentChildren",
361
- "Directive",
362
- "Host",
363
- "HostBinding",
364
- "HostListener",
365
- "Inject",
366
- "Injectable",
367
- "Input",
368
- "NgModule",
369
- "Optional",
370
- "Output",
371
- "Pipe",
372
- "Self",
373
- "SkipSelf",
374
- "ViewChild",
375
- "ViewChildren"
376
- ]
377
- }
378
- ] : "error",
377
+ "new-cap": "error",
379
378
  "no-alert": "error",
380
379
  "no-caller": "error",
381
380
  "no-cond-assign": ["error", "always"],
@@ -419,6 +418,7 @@ function javascript(options = {}) {
419
418
  "no-useless-constructor": "error",
420
419
  "no-useless-rename": "error",
421
420
  "no-useless-return": "error",
421
+ "no-var": "error",
422
422
  "object-shorthand": [
423
423
  "error",
424
424
  "always",
@@ -432,14 +432,18 @@ function javascript(options = {}) {
432
432
  "error",
433
433
  { singleReturnOnly: true, allowNamedFunctions: true }
434
434
  ],
435
+ "prefer-const": "error",
435
436
  "prefer-exponentiation-operator": "error",
436
437
  "prefer-object-spread": "error",
437
438
  "prefer-promise-reject-errors": "error",
438
439
  "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
440
+ "prefer-rest-params": "error",
441
+ "prefer-spread": "error",
439
442
  "prefer-template": "error",
440
443
  "symbol-description": "error",
441
444
  "unicode-bom": ["error", "never"],
442
- "unused-imports/no-unused-imports": isInEditor ? "warn" : "error",
445
+ "unused-imports/no-unused-imports": "error",
446
+ "no-unused-vars": "off",
443
447
  "unused-imports/no-unused-vars": [
444
448
  "error",
445
449
  {
@@ -454,64 +458,18 @@ function javascript(options = {}) {
454
458
  "valid-typeof": ["error", { requireStringLiterals: true }],
455
459
  "vars-on-top": "error",
456
460
  yoda: ["error", "never", { exceptRange: true }],
457
- "@typescript-eslint/no-unused-vars": "off",
458
- // superseded by unused-imports/no-unused-vars
459
- // TODO: check if required to apply more nx javascript rules here
461
+ "@typescript-eslint/ban-ts-comment": "error",
462
+ "@typescript-eslint/no-extra-non-null-assertion": "error",
463
+ "@typescript-eslint/no-misused-new": "error",
464
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "error",
465
+ "@typescript-eslint/no-require-imports": ["error", { allowAsImport: true }],
466
+ "@typescript-eslint/no-this-alias": "error",
460
467
  ...overrides
461
468
  }
462
469
  }
463
470
  );
464
471
  }
465
472
 
466
- async function jest(options = {}) {
467
- const {
468
- overrides = {},
469
- useJestDom = isPackageExists("@testing-library/jest-dom"),
470
- useTestingLibrary = isPackageExists("@testing-library/angular"),
471
- stylistic = true
472
- } = options;
473
- const [jestPlugin, jestDomPlugin, testingLibraryPlugin] = await Promise.all([
474
- interopDefault(import('eslint-plugin-jest')),
475
- useJestDom ? interopDefault(import('eslint-plugin-jest-dom')) : Promise.resolve(undefined),
476
- useTestingLibrary ? interopDefault(import('eslint-plugin-testing-library')) : Promise.resolve(undefined)
477
- ]);
478
- return tseslint.config({
479
- name: "fabdeh/jest/rules",
480
- plugins: {
481
- jest: jestPlugin
482
- },
483
- languageOptions: {
484
- globals: {
485
- ...globals.node,
486
- ...globals.jest
487
- }
488
- },
489
- files: [...GLOB_TESTS, `** /jest.config.${GLOB_SRC_EXT}`],
490
- extends: [
491
- jestPlugin.configs["flat/recommended"],
492
- ...stylistic ? [jestPlugin.configs["flat/style"]] : [],
493
- ...jestDomPlugin ? [jestDomPlugin.configs["flat/recommended"]] : [],
494
- ...testingLibraryPlugin ? [testingLibraryPlugin.configs["flat/angular"]] : []
495
- ],
496
- rules: {
497
- "max-classes-per-file": "off",
498
- "max-lines": "off",
499
- "@typescript-eslint/consistent-type-assertions": "off",
500
- "@typescript-eslint/no-empty-function": "off",
501
- "@typescript-eslint/no-unsafe-assignment": "off",
502
- "@typescript-eslint/no-unsafe-call": "off",
503
- "@typescript-eslint/no-unsafe-member-access": "off",
504
- "@typescript-eslint/unbound-method": "off",
505
- "jest/consistent-test-it": ["error", { fn: "test" }],
506
- "jest/prefer-spy-on": "error",
507
- "jest/require-top-level-describe": "error",
508
- "jest/unbound-method": "error",
509
- "unicorn/no-null": "off",
510
- ...overrides
511
- }
512
- });
513
- }
514
-
515
473
  function jsdoc(options = {}) {
516
474
  const { stylistic = true } = options;
517
475
  return tseslint.config(
@@ -643,28 +601,6 @@ async function markdown(options = {}) {
643
601
  files = [GLOB_MARKDOWN],
644
602
  overrides = {}
645
603
  } = options;
646
- const parserPlain = {
647
- meta: {
648
- name: "parser-plain"
649
- },
650
- parseForESLint: (code) => ({
651
- ast: {
652
- body: [],
653
- comments: [],
654
- loc: { end: code.length, start: 0 },
655
- range: [0, code.length],
656
- tokens: [],
657
- type: "Program"
658
- },
659
- // eslint-disable-next-line unicorn/no-null
660
- scopeManager: null,
661
- services: { isPlain: true },
662
- visitorKeys: {
663
- // eslint-disable-next-line @typescript-eslint/naming-convention
664
- Program: []
665
- }
666
- })
667
- };
668
604
  const markdownPlugin = await interopDefault(import('@eslint/markdown'));
669
605
  return tseslint.config(
670
606
  {
@@ -680,19 +616,16 @@ async function markdown(options = {}) {
680
616
  processor: mergeProcessors([
681
617
  markdownPlugin.processors.markdown,
682
618
  processorPassThrough
683
- ])
684
- },
685
- {
686
- name: "fabdeh/markdown/parser",
687
- language: "markdown/gfm",
688
- languageOptions: {
689
- parser: parserPlain
690
- },
691
- files
619
+ ]),
620
+ rules: {
621
+ ...markdownPlugin.configs.recommended.at(0)?.rules,
622
+ "markdown/no-duplicate-headings": "error"
623
+ }
692
624
  },
693
625
  {
694
626
  name: "fabdeh/markdown/disables",
695
627
  languageOptions: {
628
+ parser: tseslint.parser,
696
629
  parserOptions: {
697
630
  ecmaFeatures: {
698
631
  impliedStrict: true
@@ -700,8 +633,8 @@ async function markdown(options = {}) {
700
633
  }
701
634
  },
702
635
  files: [GLOB_MARKDOWN_CODE],
703
- extends: [tseslint.configs.disableTypeChecked],
704
636
  rules: {
637
+ ...tseslint.configs.disableTypeChecked.rules,
705
638
  "import-x/newline-after-import": "off",
706
639
  "no-alert": "off",
707
640
  "no-console": "off",
@@ -762,17 +695,22 @@ async function ngrx(options = {}) {
762
695
  signals = isPackageExists("@ngrx/signals")
763
696
  } = options;
764
697
  const configs = [];
698
+ let addOperatorsRules = false;
699
+ const ngrxOperatorsFiles = [];
765
700
  if (store) {
766
701
  const {
767
702
  files = DEFAULT_STORE_GLOB,
768
703
  enforceOperatorsRules = isPackageExists("@ngrx/operators"),
769
704
  overrides = {}
770
705
  } = typeof store === "object" ? store : {};
706
+ addOperatorsRules ||= enforceOperatorsRules;
707
+ ngrxOperatorsFiles.push(files);
771
708
  configs.push({
772
709
  name: "fabdeh/ngrx-store/rules",
773
710
  files,
774
- extends: [...ngrxPlugin.configs.store, ...enforceOperatorsRules ? ngrxPlugin.configs.operators : []],
711
+ plugins: { "@ngrx": ngrxPlugin },
775
712
  rules: {
713
+ ...ngrxPlugin.configs.store.find((c) => c.name === "ngrx/store")?.rules,
776
714
  "@typescript-eslint/naming-convention": [
777
715
  "error",
778
716
  ...namingConvention,
@@ -803,11 +741,14 @@ async function ngrx(options = {}) {
803
741
  enforceOperatorsRules = isPackageExists("@ngrx/operators"),
804
742
  overrides = {}
805
743
  } = typeof effects === "object" ? effects : {};
744
+ addOperatorsRules ||= enforceOperatorsRules;
745
+ ngrxOperatorsFiles.push(files);
806
746
  configs.push({
807
747
  name: "fabdeh/ngrx-effects/rules",
808
748
  files,
809
- extends: [...ngrxPlugin.configs.effects, ...enforceOperatorsRules ? ngrxPlugin.configs.operators : []],
749
+ plugins: { "@ngrx": ngrxPlugin },
810
750
  rules: {
751
+ ...ngrxPlugin.configs.effects.find((c) => c.name === "ngrx/effects")?.rules,
811
752
  "@typescript-eslint/naming-convention": [
812
753
  "error",
813
754
  ...namingConvention,
@@ -835,11 +776,14 @@ async function ngrx(options = {}) {
835
776
  { selector: "variableLike", format: ["camelCase"] },
836
777
  { selector: "memberLike", format: ["camelCase"], leadingUnderscore: "allow" }
837
778
  ];
779
+ addOperatorsRules ||= enforceOperatorsRules;
780
+ ngrxOperatorsFiles.push(files);
838
781
  configs.push({
839
782
  name: "fabdeh/ngrx-signals/rules",
840
783
  files,
841
- extends: [...ngrxPlugin.configs.signals, ...enforceOperatorsRules ? ngrxPlugin.configs.operators : []],
784
+ plugins: { "@ngrx": ngrxPlugin },
842
785
  rules: {
786
+ ...ngrxPlugin.configs.signals.find((c) => c.name === "ngrx/signals")?.rules,
843
787
  "@typescript-eslint/naming-convention": [
844
788
  "error",
845
789
  ...allowLeadingUnderscoreOnMemberLike(namingConvention),
@@ -855,6 +799,16 @@ async function ngrx(options = {}) {
855
799
  }
856
800
  });
857
801
  }
802
+ if (addOperatorsRules) {
803
+ configs.push({
804
+ name: "fabdeh/ngrx-operators/rules",
805
+ files: [...ngrxOperatorsFiles],
806
+ plugins: { "@ngrx": ngrxPlugin },
807
+ rules: {
808
+ ...ngrxPlugin.configs.operators.find((c) => c.name === "ngrx/operators")?.rules
809
+ }
810
+ });
811
+ }
858
812
  return tseslint.config(configs);
859
813
  }
860
814
 
@@ -907,9 +861,11 @@ const SORT_UNION_OR_INTERSECTION_GROUPS = [
907
861
  "unknown"
908
862
  ];
909
863
 
910
- function perfectionist() {
864
+ async function perfectionist() {
865
+ const tsconfigRootDir = await findNearestPackageJsonName() === "@fabdeh/eslint-config" ? void 0 : getWorkspaceRoot(process.cwd(), process.cwd());
911
866
  return tseslint.config({
912
867
  name: "fabdeh/perfectionist/rules",
868
+ files: [GLOB_SRC],
913
869
  plugins: {
914
870
  perfectionist: perfectionistPlugin
915
871
  },
@@ -919,7 +875,7 @@ function perfectionist() {
919
875
  "error",
920
876
  {
921
877
  groups: SORT_IMPORT_GROUPS,
922
- tsconfigRootDir: getWorkspaceRoot(process.cwd(), process.cwd()),
878
+ tsconfigRootDir,
923
879
  order: "asc",
924
880
  type: "natural",
925
881
  newlinesBetween: "never"
@@ -1308,14 +1264,13 @@ function typescript(options = {}) {
1308
1264
  name: "fabdeh/typescript/rules",
1309
1265
  files: [GLOB_TS],
1310
1266
  plugins: {
1311
- "@typescript-eslint": tseslint.plugin
1267
+ "@typescript-eslint": tseslint.plugin,
1268
+ "unused-imports": unusedImports
1312
1269
  },
1313
- extends: [
1314
- eslint.configs.recommended,
1315
- ...tseslint.configs.strictTypeChecked,
1316
- ...stylistic ? tseslint.configs.stylisticTypeChecked : []
1317
- ],
1318
1270
  rules: {
1271
+ ...tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/eslint-recommended")?.rules,
1272
+ ...tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/strict-type-checked")?.rules,
1273
+ ...stylistic ? tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/stylistic-type-checked")?.rules : {},
1319
1274
  "@typescript-eslint/array-type": ["error", { default: "array" }],
1320
1275
  "@typescript-eslint/consistent-indexed-object-style": "error",
1321
1276
  "@typescript-eslint/consistent-type-assertions": [
@@ -1323,7 +1278,14 @@ function typescript(options = {}) {
1323
1278
  { assertionStyle: "as", objectLiteralTypeAssertions: "never" }
1324
1279
  ],
1325
1280
  "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
1281
+ "@typescript-eslint/consistent-type-exports": "error",
1282
+ "@typescript-eslint/consistent-type-imports": ["error", {
1283
+ disallowTypeAnnotations: false,
1284
+ fixStyle: "separate-type-imports",
1285
+ prefer: "type-imports"
1286
+ }],
1326
1287
  "@typescript-eslint/dot-notation": "error",
1288
+ "@typescript-eslint/explicit-module-boundary-types": "error",
1327
1289
  "@typescript-eslint/explicit-function-return-type": [
1328
1290
  "error",
1329
1291
  {
@@ -1347,12 +1309,11 @@ function typescript(options = {}) {
1347
1309
  "@typescript-eslint/no-extraneous-class": ["error", { allowStaticOnly: true, allowWithDecorator: true }],
1348
1310
  "@typescript-eslint/no-invalid-void-type": "error",
1349
1311
  "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
1350
- "@typescript-eslint/no-require-imports": "error",
1351
1312
  "@typescript-eslint/only-throw-error": "error",
1352
1313
  "@typescript-eslint/no-unnecessary-condition": "error",
1353
1314
  "@typescript-eslint/no-unnecessary-type-arguments": "error",
1354
1315
  "@typescript-eslint/no-unsafe-unary-minus": "error",
1355
- "@typescript-eslint/parameter-properties": ["error", { prefer: "parameter-property" }],
1316
+ "@typescript-eslint/parameter-properties": "error",
1356
1317
  "@typescript-eslint/prefer-enum-initializers": "error",
1357
1318
  "@typescript-eslint/prefer-for-of": "error",
1358
1319
  "@typescript-eslint/prefer-function-type": "error",
@@ -1370,6 +1331,7 @@ function typescript(options = {}) {
1370
1331
  "@typescript-eslint/switch-exhaustiveness-check": "error",
1371
1332
  "@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
1372
1333
  "@typescript-eslint/unified-signatures": "error",
1334
+ "@typescript-eslint/no-unused-vars": "off",
1373
1335
  ...overrides
1374
1336
  }
1375
1337
  }
@@ -1380,9 +1342,11 @@ function unicorn(options = {}) {
1380
1342
  return tseslint.config({
1381
1343
  name: "fabdeh/unicorn/rules",
1382
1344
  plugins: { unicorn: unicornPlugin },
1345
+ files: [GLOB_SRC],
1383
1346
  rules: {
1384
- ...options.allRecommended ? unicornPlugin.configs["flat/recommended"].rules : {
1347
+ ...options.allRecommended ? unicornPlugin.configs.recommended.rules : {
1385
1348
  "unicorn/catch-error-name": "error",
1349
+ "unicorn/consistent-date-clone": "error",
1386
1350
  "unicorn/consistent-empty-array-spread": "error",
1387
1351
  "unicorn/consistent-existence-index-check": "error",
1388
1352
  "unicorn/consistent-function-scoping": ["error", { checkArrowFunctions: false }],
@@ -1404,7 +1368,7 @@ function unicorn(options = {}) {
1404
1368
  "unicorn/no-empty-file": "error",
1405
1369
  "unicorn/no-for-loop": "error",
1406
1370
  "unicorn/no-hex-escape": "error",
1407
- "unicorn/no-instanceof-array": "error",
1371
+ "unicorn/no-instanceof-builtins": "error",
1408
1372
  "unicorn/no-invalid-fetch-options": "error",
1409
1373
  "unicorn/no-invalid-remove-event-listener": "error",
1410
1374
  "unicorn/no-length-as-slice-end": "error",
@@ -1483,12 +1447,16 @@ async function vitest(options = {}) {
1483
1447
  } = options;
1484
1448
  const [vitestPlugin, jestDomPlugin, testingLibraryPlugin] = await Promise.all([
1485
1449
  interopDefault(import('@vitest/eslint-plugin')),
1486
- useJestDom ? interopDefault(import('eslint-plugin-jest-dom')) : Promise.resolve(undefined),
1487
- useTestingLibrary ? interopDefault(import('eslint-plugin-testing-library')) : Promise.resolve(undefined)
1450
+ useJestDom ? interopDefault(import('eslint-plugin-jest-dom')) : Promise.resolve(void 0),
1451
+ useTestingLibrary ? interopDefault(import('eslint-plugin-testing-library')) : Promise.resolve(void 0)
1488
1452
  ]);
1489
1453
  return tseslint.config({
1490
1454
  name: "fabdeh/vitest/rules",
1491
- plugins: { vitest: vitestPlugin },
1455
+ plugins: {
1456
+ vitest: vitestPlugin,
1457
+ ...jestDomPlugin ? { "jest-dom": jestDomPlugin } : {},
1458
+ ...testingLibraryPlugin ? { "testing-library": testingLibraryPlugin } : {}
1459
+ },
1492
1460
  languageOptions: {
1493
1461
  globals: {
1494
1462
  ...globals.node,
@@ -1502,12 +1470,10 @@ async function vitest(options = {}) {
1502
1470
  }
1503
1471
  },
1504
1472
  files: [...GLOB_TESTS],
1505
- extends: [
1506
- vitestPlugin.configs.recommended,
1507
- ...jestDomPlugin ? [jestDomPlugin.configs["flat/recommended"]] : [],
1508
- ...testingLibraryPlugin ? [testingLibraryPlugin.configs["flat/angular"]] : []
1509
- ],
1510
1473
  rules: {
1474
+ ...vitestPlugin.configs.recommended.rules,
1475
+ ...jestDomPlugin?.configs["flat/recommended"].rules,
1476
+ ...testingLibraryPlugin?.configs["flat/angular"].rules,
1511
1477
  "max-classes-per-file": "off",
1512
1478
  "max-lines": "off",
1513
1479
  "@typescript-eslint/consistent-type-assertions": "off",
@@ -1598,9 +1564,7 @@ function mergePrettierOptions(options, overrides = {}) {
1598
1564
  ...options,
1599
1565
  ...overrides,
1600
1566
  plugins: [
1601
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1602
1567
  ...overrides.plugins ?? [],
1603
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1604
1568
  ...options.plugins ?? []
1605
1569
  ]
1606
1570
  };
@@ -1620,8 +1584,8 @@ async function formatters(options = {}, stylistic = {}) {
1620
1584
  }
1621
1585
  await ensurePackages([
1622
1586
  "eslint-plugin-format",
1623
- options.markdown && options.slidev ? "prettier-plugin-slidev" : undefined,
1624
- options.xml || options.svg ? "@prettier/plugin-xml" : undefined
1587
+ options.markdown && options.slidev ? "prettier-plugin-slidev" : void 0,
1588
+ options.xml || options.svg ? "@prettier/plugin-xml" : void 0
1625
1589
  ]);
1626
1590
  const {
1627
1591
  indent,
@@ -1822,23 +1786,11 @@ async function createConfig(options = {}, ...userConfigs) {
1822
1786
  const {
1823
1787
  angular: enableAngular = isPackageExists("@angular/core"),
1824
1788
  gitignore: enableGitignore = true,
1825
- isInEditor = isInEditorEnv(),
1826
- jest: enableJest = isPackageExists("jest"),
1827
1789
  ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)),
1828
1790
  tailwindcss: enableTailwind = isPackageExists("tailwindcss"),
1829
1791
  unicorn: enableUnicorn = true,
1830
1792
  vitest: enableVitest = isPackageExists("vitest")
1831
1793
  } = options;
1832
- if (isInEditor) {
1833
- console.log(
1834
- "[@fabdeh/eslint-config] Detected running in editor, some rules are configured as warn or completely turned off."
1835
- );
1836
- }
1837
- if (enableJest && enableVitest) {
1838
- throw new Error(
1839
- '[@fabdeh/eslint-config] Detected that both "jest" and "vitest" are enabled which is not supported. Manually disable or uninstall one of them.'
1840
- );
1841
- }
1842
1794
  const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
1843
1795
  const configs = [];
1844
1796
  if (enableGitignore) {
@@ -1856,10 +1808,9 @@ async function createConfig(options = {}, ...userConfigs) {
1856
1808
  );
1857
1809
  }
1858
1810
  }
1859
- const allowAngularDecorator = options.angular !== false;
1860
1811
  configs.push(
1861
1812
  ignores(options.ignores),
1862
- javascript({ isInEditor, overrides: options.javascript?.overrides, allowAngularDecorator }),
1813
+ javascript({ overrides: options.javascript?.overrides }),
1863
1814
  typescript({
1864
1815
  stylistic: stylisticOptions,
1865
1816
  parserOptions: options.typescript?.parserOptions,
@@ -1882,13 +1833,6 @@ async function createConfig(options = {}, ...userConfigs) {
1882
1833
  if (enableNgrx) {
1883
1834
  configs.push(ngrx(typeof enableNgrx === "object" ? enableNgrx : {}));
1884
1835
  }
1885
- if (enableJest) {
1886
- configs.push(
1887
- jest(
1888
- typeof enableJest === "object" ? { ...enableJest, stylistic: stylisticOptions } : { stylistic: stylisticOptions }
1889
- )
1890
- );
1891
- }
1892
1836
  if (enableVitest) {
1893
1837
  configs.push(vitest(typeof enableVitest === "object" ? enableVitest : {}));
1894
1838
  }
@@ -1937,4 +1881,4 @@ async function createConfig(options = {}, ...userConfigs) {
1937
1881
  return tseslint.config(...await Promise.all(configs), ...await Promise.all(userConfigs));
1938
1882
  }
1939
1883
 
1940
- export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, getWorkspaceRoot, ignores, imports, interopDefault, isInEditorEnv, isPackageInScope, javascript, jest, jsdoc, jsonc, markdown, ngrx, perfectionist, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toArray, toml, typescript, unicorn, vitest, yaml };
1884
+ export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };