js-style-kit 0.2.11 → 0.3.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.
Files changed (118) hide show
  1. package/README.md +74 -11
  2. package/dist/bin/index.js +12 -16
  3. package/dist/bin/index.js.map +1 -1
  4. package/dist/index.d.ts +130 -9
  5. package/dist/index.js +301 -83
  6. package/dist/index.js.map +1 -1
  7. package/package.json +19 -14
  8. package/dist/eslint/base/config.d.ts +0 -17
  9. package/dist/eslint/base/config.js +0 -457
  10. package/dist/eslint/base/config.js.map +0 -1
  11. package/dist/eslint/base/rules.d.ts +0 -18
  12. package/dist/eslint/base/rules.js +0 -425
  13. package/dist/eslint/base/rules.js.map +0 -1
  14. package/dist/eslint/base/types.d.ts +0 -21
  15. package/dist/eslint/base/types.js +0 -1
  16. package/dist/eslint/base/types.js.map +0 -1
  17. package/dist/eslint/constants.d.ts +0 -28
  18. package/dist/eslint/constants.js +0 -25
  19. package/dist/eslint/constants.js.map +0 -1
  20. package/dist/eslint/ignores.d.ts +0 -19
  21. package/dist/eslint/ignores.js +0 -42
  22. package/dist/eslint/ignores.js.map +0 -1
  23. package/dist/eslint/index.d.ts +0 -55
  24. package/dist/eslint/index.js +0 -1410
  25. package/dist/eslint/index.js.map +0 -1
  26. package/dist/eslint/jsdoc/config.d.ts +0 -14
  27. package/dist/eslint/jsdoc/config.js +0 -109
  28. package/dist/eslint/jsdoc/config.js.map +0 -1
  29. package/dist/eslint/jsdoc/rules.d.ts +0 -15
  30. package/dist/eslint/jsdoc/rules.js +0 -73
  31. package/dist/eslint/jsdoc/rules.js.map +0 -1
  32. package/dist/eslint/jsdoc/types.d.ts +0 -52
  33. package/dist/eslint/jsdoc/types.js +0 -1
  34. package/dist/eslint/jsdoc/types.js.map +0 -1
  35. package/dist/eslint/nextjs/config.d.ts +0 -12
  36. package/dist/eslint/nextjs/config.js +0 -62
  37. package/dist/eslint/nextjs/config.js.map +0 -1
  38. package/dist/eslint/nextjs/rules.d.ts +0 -8
  39. package/dist/eslint/nextjs/rules.js +0 -28
  40. package/dist/eslint/nextjs/rules.js.map +0 -1
  41. package/dist/eslint/nextjs/types.d.ts +0 -29
  42. package/dist/eslint/nextjs/types.js +0 -1
  43. package/dist/eslint/nextjs/types.js.map +0 -1
  44. package/dist/eslint/perfectionist/config.d.ts +0 -7
  45. package/dist/eslint/perfectionist/config.js +0 -65
  46. package/dist/eslint/perfectionist/config.js.map +0 -1
  47. package/dist/eslint/perfectionist/rules.d.ts +0 -12
  48. package/dist/eslint/perfectionist/rules.js +0 -31
  49. package/dist/eslint/perfectionist/rules.js.map +0 -1
  50. package/dist/eslint/prefer-arrow-function/config.d.ts +0 -12
  51. package/dist/eslint/prefer-arrow-function/config.js +0 -45
  52. package/dist/eslint/prefer-arrow-function/config.js.map +0 -1
  53. package/dist/eslint/prefer-arrow-function/types.d.ts +0 -17
  54. package/dist/eslint/prefer-arrow-function/types.js +0 -1
  55. package/dist/eslint/prefer-arrow-function/types.js.map +0 -1
  56. package/dist/eslint/react/config.d.ts +0 -18
  57. package/dist/eslint/react/config.js +0 -186
  58. package/dist/eslint/react/config.js.map +0 -1
  59. package/dist/eslint/react/rules.d.ts +0 -26
  60. package/dist/eslint/react/rules.js +0 -132
  61. package/dist/eslint/react/rules.js.map +0 -1
  62. package/dist/eslint/react-compiler/config.d.ts +0 -12
  63. package/dist/eslint/react-compiler/config.js +0 -39
  64. package/dist/eslint/react-compiler/config.js.map +0 -1
  65. package/dist/eslint/react-refresh/config.d.ts +0 -16
  66. package/dist/eslint/react-refresh/config.js +0 -55
  67. package/dist/eslint/react-refresh/config.js.map +0 -1
  68. package/dist/eslint/react-refresh/rules.d.ts +0 -38
  69. package/dist/eslint/react-refresh/rules.js +0 -19
  70. package/dist/eslint/react-refresh/rules.js.map +0 -1
  71. package/dist/eslint/storybook/config.d.ts +0 -13
  72. package/dist/eslint/storybook/config.js +0 -67
  73. package/dist/eslint/storybook/config.js.map +0 -1
  74. package/dist/eslint/testing/config.d.ts +0 -25
  75. package/dist/eslint/testing/config.js +0 -169
  76. package/dist/eslint/testing/config.js.map +0 -1
  77. package/dist/eslint/testing/jest-rules.d.ts +0 -14
  78. package/dist/eslint/testing/jest-rules.js +0 -44
  79. package/dist/eslint/testing/jest-rules.js.map +0 -1
  80. package/dist/eslint/testing/vitest-rules.d.ts +0 -14
  81. package/dist/eslint/testing/vitest-rules.js +0 -50
  82. package/dist/eslint/testing/vitest-rules.js.map +0 -1
  83. package/dist/eslint/turbo/config.d.ts +0 -12
  84. package/dist/eslint/turbo/config.js +0 -39
  85. package/dist/eslint/turbo/config.js.map +0 -1
  86. package/dist/eslint/turbo/types.d.ts +0 -11
  87. package/dist/eslint/turbo/types.js +0 -1
  88. package/dist/eslint/turbo/types.js.map +0 -1
  89. package/dist/eslint/types.d.ts +0 -11
  90. package/dist/eslint/types.js +0 -1
  91. package/dist/eslint/types.js.map +0 -1
  92. package/dist/eslint/typescript/config.d.ts +0 -11
  93. package/dist/eslint/typescript/config.js +0 -186
  94. package/dist/eslint/typescript/config.js.map +0 -1
  95. package/dist/eslint/typescript/rules.d.ts +0 -8
  96. package/dist/eslint/typescript/rules.js +0 -135
  97. package/dist/eslint/typescript/rules.js.map +0 -1
  98. package/dist/eslint/typescript/types.d.ts +0 -7
  99. package/dist/eslint/typescript/types.js +0 -1
  100. package/dist/eslint/typescript/types.js.map +0 -1
  101. package/dist/eslint/unicorn/config.d.ts +0 -11
  102. package/dist/eslint/unicorn/config.js +0 -113
  103. package/dist/eslint/unicorn/config.js.map +0 -1
  104. package/dist/eslint/unicorn/rules.d.ts +0 -8
  105. package/dist/eslint/unicorn/rules.js +0 -79
  106. package/dist/eslint/unicorn/rules.js.map +0 -1
  107. package/dist/modules.d.d.ts +0 -3
  108. package/dist/modules.d.js +0 -1
  109. package/dist/modules.d.js.map +0 -1
  110. package/dist/prettier/index.d.ts +0 -34
  111. package/dist/prettier/index.js +0 -132
  112. package/dist/prettier/index.js.map +0 -1
  113. package/dist/prettier/patch-tailwind-plugin.d.ts +0 -9
  114. package/dist/prettier/patch-tailwind-plugin.js +0 -72
  115. package/dist/prettier/patch-tailwind-plugin.js.map +0 -1
  116. package/dist/utils/is-type.d.ts +0 -44
  117. package/dist/utils/is-type.js +0 -28
  118. package/dist/utils/is-type.js.map +0 -1
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ var configNames = {
11
11
  base: "base",
12
12
  disableTypeChecked: "typescript-eslint/disable-type-checked",
13
13
  ignores: "ignores",
14
+ import: "import",
14
15
  jsdoc: "jsdoc",
15
16
  markdown: "markdown",
16
17
  nextjs: "nextjs",
@@ -27,9 +28,30 @@ var configNames = {
27
28
  typescriptTesting: "tseslint-testing",
28
29
  unicorn: "unicorn"
29
30
  };
31
+ var pluginPrefixMap = /* @__PURE__ */ new Map([
32
+ ["@typescript-eslint", configNames.typescript],
33
+ ["import", configNames.import],
34
+ ["import-x", configNames.import],
35
+ ["jest", configNames.testing],
36
+ ["jsdoc", configNames.jsdoc],
37
+ ["nextjs", configNames.nextjs],
38
+ ["perfectionist", configNames.perfectionist],
39
+ ["react", configNames.react],
40
+ ["react-compiler", configNames.reactCompiler],
41
+ ["react-hooks", configNames.react],
42
+ ["react-refresh", configNames.reactRefresh],
43
+ ["storybook", configNames.storybook],
44
+ ["turbo", configNames.turbo],
45
+ ["unicorn", configNames.unicorn],
46
+ ["vitest", configNames.testing]
47
+ ]);
30
48
 
31
49
  // src/eslint/base/rules.ts
32
- var baseEslintRules = (functionStyle) => ({
50
+ var baseEslintRules = (functionStyle, typescript) => ({
51
+ ...!typescript ? {
52
+ "no-unused-expressions": "warn",
53
+ "no-unused-vars": "warn"
54
+ } : {},
33
55
  /**
34
56
  * Require return statements in array methods callbacks.
35
57
  *
@@ -84,10 +106,8 @@ var baseEslintRules = (functionStyle) => ({
84
106
  * 🚫 Not fixable - https://eslint.org/docs/rules/func-names
85
107
  */
86
108
  "func-names": ["warn", "as-needed"],
87
- "func-style": (
88
- // if arrow function, we use the prefer-arrow-functions plugin
89
- functionStyle === "off" || functionStyle === "arrow" ? "off" : ["warn", functionStyle, { allowArrowFunctions: true }]
90
- ),
109
+ // if arrow function, we use the prefer-arrow-functions plugin
110
+ ...functionStyle === "off" ? { "func-style": "off" } : functionStyle === "arrow" ? { "func-style": "off" } : { "func-style": ["warn", functionStyle, { allowArrowFunctions: true }] },
91
111
  /**
92
112
  * Require grouped accessor pairs in object literals and classes.
93
113
  *
@@ -451,13 +471,17 @@ var baseEslintRules = (functionStyle) => ({
451
471
  });
452
472
 
453
473
  // src/eslint/base/config.ts
454
- var baseEslintConfig = (functionStyle) => ({
474
+ var baseEslintConfig = (functionStyle, typescript, customRules) => ({
455
475
  languageOptions: {
456
- ecmaVersion: 2022
476
+ ecmaVersion: "latest",
477
+ sourceType: "module"
457
478
  },
458
479
  linterOptions: { reportUnusedDisableDirectives: true },
459
480
  name: configNames.base,
460
- rules: baseEslintRules(functionStyle)
481
+ rules: {
482
+ ...baseEslintRules(functionStyle, typescript),
483
+ ...customRules ?? {}
484
+ }
461
485
  });
462
486
 
463
487
  // src/eslint/ignores.ts
@@ -467,9 +491,7 @@ var ignoresConfig = ({
467
491
  userIgnores = []
468
492
  } = {}) => ({
469
493
  ignores: [
470
- "**/node_modules/",
471
494
  "**/dist/",
472
- ".git/",
473
495
  ...next ? [".next"] : [],
474
496
  ...storybook ? ["!.storybook"] : [],
475
497
  ...userIgnores
@@ -477,6 +499,110 @@ var ignoresConfig = ({
477
499
  name: configNames.ignores
478
500
  });
479
501
 
502
+ // src/eslint/import/config.ts
503
+ import tsParser from "@typescript-eslint/parser";
504
+ import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
505
+ import importXPlugin from "eslint-plugin-import-x";
506
+
507
+ // src/eslint/import/rules.ts
508
+ var importRules = (typescript) => ({
509
+ // these rules are better handled by typescript
510
+ ...!typescript ? {
511
+ "import-x/default": "warn",
512
+ "import-x/export": "warn",
513
+ "import-x/named": "warn",
514
+ "import-x/namespace": "warn",
515
+ "import-x/no-unresolved": "warn"
516
+ } : {},
517
+ /**
518
+ * Disallow non-import statements appearing before import statements.
519
+ *
520
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/first.md
521
+ */
522
+ "import-x/first": "warn",
523
+ /**
524
+ * Require a newline after the last import-x/require.
525
+ *
526
+ * 🔧 Fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/newline-after-import.md
527
+ */
528
+ "import-x/newline-after-import": "warn",
529
+ /**
530
+ * Disallow import of modules using absolute paths.
531
+ *
532
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-absolute-path.md
533
+ */
534
+ "import-x/no-absolute-path": "warn",
535
+ /**
536
+ * Disallow cyclical dependencies between modules.
537
+ *
538
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-cycle.md
539
+ */
540
+ "import-x/no-cycle": "warn",
541
+ "import-x/no-duplicates": "warn",
542
+ /**
543
+ * Disallow the use of extraneous packages.
544
+ *
545
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-extraneous-dependencies.md
546
+ */
547
+ "import-x/no-extraneous-dependencies": ["warn", { includeTypes: true }],
548
+ /**
549
+ * Disallow mutable exports.
550
+ *
551
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-mutable-exports.md
552
+ */
553
+ "import-x/no-mutable-exports": "warn",
554
+ // red flags (thus, warnings)
555
+ "import-x/no-named-as-default": "warn",
556
+ "import-x/no-named-as-default-member": "warn",
557
+ /**
558
+ * Disallow importing packages through relative paths.
559
+ *
560
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-relative-packages.md
561
+ */
562
+ "import-x/no-relative-packages": "warn",
563
+ /**
564
+ * Disallow a module from importing itself.
565
+ *
566
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-self-import.md
567
+ */
568
+ "import-x/no-self-import": "warn",
569
+ /**
570
+ * Ensures that there are no useless path segments.
571
+ *
572
+ * 🚫 Not fixable - https://github.com/import-js/eslint-plugin-import-x/blob/main/docs/rules/no-useless-path-segments.md
573
+ */
574
+ "import-x/no-useless-path-segments": ["warn"]
575
+ });
576
+
577
+ // src/eslint/import/config.ts
578
+ var importConfig = (typescript, customRules) => ({
579
+ languageOptions: {
580
+ ecmaVersion: "latest",
581
+ parser: tsParser,
582
+ sourceType: "module"
583
+ },
584
+ name: configNames.import,
585
+ plugins: {
586
+ "import-x": importXPlugin
587
+ },
588
+ rules: {
589
+ ...importRules(typescript),
590
+ ...customRules ?? {}
591
+ },
592
+ settings: {
593
+ "import-x/resolver": {
594
+ node: true,
595
+ typescript
596
+ },
597
+ "import-x/resolver-next": [
598
+ createTypeScriptImportResolver({
599
+ alwaysTryTypes: true,
600
+ bun: true
601
+ })
602
+ ]
603
+ }
604
+ });
605
+
480
606
  // src/eslint/jsdoc/config.ts
481
607
  import jsdoc from "eslint-plugin-jsdoc";
482
608
 
@@ -551,14 +677,17 @@ var jsdocRules = (requireJsdoc = false, typescript = true) => ({
551
677
  });
552
678
 
553
679
  // src/eslint/jsdoc/config.ts
554
- var jsdocConfig = (requireJsdoc = false, typescript = true) => ({
680
+ var jsdocConfig = (requireJsdoc = false, customRules) => ({
555
681
  files: ["**/*.{js,jsx,ts,tsx,cjs,mjs}"],
556
682
  ignores: ["**/*.{test,spec}.{js,jsx,ts,tsx,cjs,mjs}"],
557
683
  name: configNames.jsdoc,
558
684
  plugins: {
559
685
  jsdoc
560
686
  },
561
- rules: jsdocRules(requireJsdoc, typescript)
687
+ rules: {
688
+ ...jsdocRules(requireJsdoc),
689
+ ...customRules ?? {}
690
+ }
562
691
  });
563
692
 
564
693
  // src/eslint/nextjs/config.ts
@@ -590,12 +719,15 @@ var nextjsRules = {
590
719
  };
591
720
 
592
721
  // src/eslint/nextjs/config.ts
593
- var nextjsConfig = () => ({
722
+ var nextjsConfig = (customRules) => ({
594
723
  name: configNames.nextjs,
595
724
  plugins: {
596
725
  nextjs
597
726
  },
598
- rules: nextjsRules
727
+ rules: {
728
+ ...nextjsRules,
729
+ ...customRules ?? {}
730
+ }
599
731
  });
600
732
 
601
733
  // src/eslint/perfectionist/config.ts
@@ -630,17 +762,20 @@ var perfectionistRules = {
630
762
  };
631
763
 
632
764
  // src/eslint/perfectionist/config.ts
633
- var perfectionistConfig = {
765
+ var perfectionistConfig = (customRules) => ({
634
766
  name: configNames.perfectionist,
635
767
  plugins: {
636
768
  perfectionist
637
769
  },
638
- rules: perfectionistRules
639
- };
770
+ rules: {
771
+ ...perfectionistRules,
772
+ ...customRules ?? {}
773
+ }
774
+ });
640
775
 
641
776
  // src/eslint/prefer-arrow-function/config.ts
642
777
  import preferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
643
- var preferArrowFunctionConfig = () => ({
778
+ var preferArrowFunctionConfig = (customRules) => ({
644
779
  name: configNames.preferArrowFunction,
645
780
  plugins: {
646
781
  "prefer-arrow-functions": preferArrowFunctions
@@ -652,21 +787,59 @@ var preferArrowFunctionConfig = () => ({
652
787
  returnStyle: "unchanged",
653
788
  singleReturnOnly: false
654
789
  }
655
- ]
790
+ ],
791
+ ...customRules ?? {}
656
792
  }
657
793
  });
658
794
 
795
+ // src/eslint/process-custom-rules.ts
796
+ var processCustomRules = (customRules) => {
797
+ const categorizedRules = Object.values(configNames).reduce(
798
+ (acc, configName) => {
799
+ acc[configName] = {};
800
+ return acc;
801
+ },
802
+ {}
803
+ );
804
+ for (const [ruleKey, ruleValue] of Object.entries(customRules)) {
805
+ if (!ruleKey.includes("/") && !ruleKey.startsWith("@")) {
806
+ categorizedRules[configNames.base][ruleKey] = ruleValue;
807
+ continue;
808
+ }
809
+ let prefix = null;
810
+ if (ruleKey.startsWith("@")) {
811
+ const firstSlashIndex = ruleKey.indexOf("/");
812
+ if (firstSlashIndex !== -1) {
813
+ prefix = ruleKey.substring(0, firstSlashIndex);
814
+ }
815
+ } else {
816
+ const firstSlashIndex = ruleKey.indexOf("/");
817
+ if (firstSlashIndex !== -1) {
818
+ prefix = ruleKey.substring(0, firstSlashIndex);
819
+ }
820
+ }
821
+ const configName = prefix ? pluginPrefixMap.get(prefix) ?? configNames.base : configNames.base;
822
+ categorizedRules[configName][ruleKey] = ruleValue;
823
+ }
824
+ return Object.entries(categorizedRules).reduce((acc, [configName, rules2]) => {
825
+ if (Object.keys(rules2).length > 0) {
826
+ acc[configName] = rules2;
827
+ }
828
+ return acc;
829
+ }, {});
830
+ };
831
+
659
832
  // src/eslint/react-compiler/config.ts
660
833
  import reactCompiler from "eslint-plugin-react-compiler";
661
- var reactCompilerEslintConfig = {
834
+ var reactCompilerEslintConfig = (customRules) => ({
662
835
  name: configNames.reactCompiler,
663
836
  plugins: {
664
837
  "react-compiler": reactCompiler
665
838
  },
666
- rules: {
839
+ rules: customRules ?? {
667
840
  "react-compiler/react-compiler": "warn"
668
841
  }
669
- };
842
+ });
670
843
 
671
844
  // src/eslint/react-refresh/config.ts
672
845
  import reactRefresh from "eslint-plugin-react-refresh";
@@ -688,13 +861,13 @@ var reactRefreshRules = {
688
861
  };
689
862
 
690
863
  // src/eslint/react-refresh/config.ts
691
- var reactRefreshEslintConfig = () => {
864
+ var reactRefreshEslintConfig = (customRules) => {
692
865
  return {
693
866
  name: configNames.reactRefresh,
694
867
  plugins: {
695
868
  "react-refresh": reactRefresh
696
869
  },
697
- rules: reactRefreshRules
870
+ rules: customRules ?? reactRefreshRules
698
871
  };
699
872
  };
700
873
 
@@ -833,7 +1006,7 @@ var reactRules = (functionStyle, typescript) => {
833
1006
  };
834
1007
 
835
1008
  // src/eslint/react/config.ts
836
- var reactEslintConfig = (functionStyle, typescript) => {
1009
+ var reactEslintConfig = (functionStyle, typescript, customRules) => {
837
1010
  return {
838
1011
  languageOptions: {
839
1012
  globals: {
@@ -850,7 +1023,10 @@ var reactEslintConfig = (functionStyle, typescript) => {
850
1023
  react,
851
1024
  "react-hooks": pluginReactHooks
852
1025
  },
853
- rules: reactRules(functionStyle, typescript),
1026
+ rules: {
1027
+ ...reactRules(functionStyle, typescript),
1028
+ ...customRules ?? {}
1029
+ },
854
1030
  settings: {
855
1031
  react: {
856
1032
  version: "detect"
@@ -861,7 +1037,7 @@ var reactEslintConfig = (functionStyle, typescript) => {
861
1037
 
862
1038
  // src/eslint/storybook/config.ts
863
1039
  import storybookPlugin from "eslint-plugin-storybook";
864
- var storybookConfig = [
1040
+ var storybookConfig = (customRules) => [
865
1041
  {
866
1042
  files: [
867
1043
  "**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)",
@@ -872,6 +1048,7 @@ var storybookConfig = [
872
1048
  storybook: storybookPlugin
873
1049
  },
874
1050
  rules: {
1051
+ // Default Storybook rules
875
1052
  "import/no-anonymous-default-export": "off",
876
1053
  "react-hooks/rules-of-hooks": "off",
877
1054
  "storybook/await-interactions": "warn",
@@ -884,7 +1061,9 @@ var storybookConfig = [
884
1061
  "storybook/prefer-pascal-case": "warn",
885
1062
  "storybook/story-exports": "warn",
886
1063
  "storybook/use-storybook-expect": "warn",
887
- "storybook/use-storybook-testing-library": "warn"
1064
+ "storybook/use-storybook-testing-library": "warn",
1065
+ // Merge custom rules
1066
+ ...customRules ?? {}
888
1067
  }
889
1068
  },
890
1069
  {
@@ -1003,7 +1182,7 @@ var testingConfig = ({
1003
1182
  formattingRules: true,
1004
1183
  framework: "vitest",
1005
1184
  itOrTest: "test"
1006
- }) => ({
1185
+ }, customRules) => ({
1007
1186
  files: files ?? ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1008
1187
  languageOptions: {
1009
1188
  globals: framework === "vitest" ? { ...vitest.environments.env.globals } : jest.environments.globals.globals
@@ -1032,7 +1211,8 @@ var testingConfig = ({
1032
1211
  "jest/padding-around-describe-blocks": "warn",
1033
1212
  "jest/padding-around-expect-groups": "warn",
1034
1213
  "jest/padding-around-test-blocks": "warn"
1035
- } : {}
1214
+ } : {},
1215
+ ...customRules ?? {}
1036
1216
  },
1037
1217
  ...framework !== "jest" && framework !== "vitest" ? {
1038
1218
  settings: {
@@ -1045,12 +1225,12 @@ var testingConfig = ({
1045
1225
 
1046
1226
  // src/eslint/turbo/config.ts
1047
1227
  import turbo from "eslint-plugin-turbo";
1048
- var turboConfig = () => ({
1228
+ var turboConfig = (customRules) => ({
1049
1229
  name: configNames.turbo,
1050
1230
  plugins: {
1051
1231
  turbo
1052
1232
  },
1053
- rules: {
1233
+ rules: customRules ?? {
1054
1234
  "turbo/no-undeclared-env-vars": "warn"
1055
1235
  }
1056
1236
  });
@@ -1150,7 +1330,12 @@ var tseslintRules = {
1150
1330
  "@typescript-eslint/prefer-includes": "warn",
1151
1331
  "@typescript-eslint/prefer-literal-enum-member": "warn",
1152
1332
  "@typescript-eslint/prefer-namespace-keyword": "warn",
1153
- "@typescript-eslint/prefer-nullish-coalescing": "warn",
1333
+ "@typescript-eslint/prefer-nullish-coalescing": [
1334
+ "warn",
1335
+ {
1336
+ ignorePrimitives: { string: true }
1337
+ }
1338
+ ],
1154
1339
  "@typescript-eslint/prefer-optional-chain": "warn",
1155
1340
  "@typescript-eslint/prefer-promise-reject-errors": "warn",
1156
1341
  "@typescript-eslint/prefer-reduce-type-parameter": "warn",
@@ -1191,7 +1376,7 @@ var tseslintRules = {
1191
1376
  };
1192
1377
 
1193
1378
  // src/eslint/typescript/config.ts
1194
- var tseslintConfig = (tsconfigPath) => {
1379
+ var tseslintConfig = (tsconfigPath, customRules) => {
1195
1380
  const userCwd = process.cwd();
1196
1381
  return tseslint.config(
1197
1382
  {
@@ -1206,7 +1391,10 @@ var tseslintConfig = (tsconfigPath) => {
1206
1391
  plugins: {
1207
1392
  "@typescript-eslint": tseslint.plugin
1208
1393
  },
1209
- rules: tseslintRules
1394
+ rules: {
1395
+ ...tseslintRules,
1396
+ ...customRules ?? {}
1397
+ }
1210
1398
  },
1211
1399
  {
1212
1400
  // disable type-aware linting on JS files
@@ -1296,108 +1484,138 @@ var rules = {
1296
1484
  };
1297
1485
 
1298
1486
  // src/eslint/unicorn/config.ts
1299
- var unicornConfig = {
1487
+ var unicornConfig = (customRules) => ({
1300
1488
  name: configNames.unicorn,
1301
1489
  plugins: {
1302
1490
  unicorn
1303
1491
  },
1304
- rules
1305
- };
1492
+ rules: {
1493
+ ...rules,
1494
+ ...customRules ?? {}
1495
+ }
1496
+ });
1306
1497
 
1307
1498
  // src/eslint/index.ts
1499
+ var defaultTestingConfig = {
1500
+ filenamePattern: "test",
1501
+ files: ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1502
+ formattingRules: true,
1503
+ framework: "vitest",
1504
+ itOrTest: "it"
1505
+ };
1308
1506
  var eslintConfig = ({
1309
1507
  functionStyle = "arrow",
1310
1508
  ignores = [],
1509
+ importPlugin = true,
1311
1510
  jsdoc: jsdoc2 = { requireJsdoc: false },
1312
1511
  react: react2 = false,
1512
+ rules: rules2,
1313
1513
  sorting = true,
1314
1514
  storybook = false,
1315
- testing,
1316
- /**
1317
- * Some preceding documentation...
1318
- *
1319
- * @param options.turbo - Whether to include Turborepo rules. Defaults to false.
1320
- *
1321
- * Some following documentation...
1322
- */
1515
+ testing = defaultTestingConfig,
1323
1516
  turbo: turbo2 = false,
1324
1517
  typescript = true,
1325
1518
  unicorn: unicorn2 = true
1326
1519
  } = {}, ...additionalConfigs) => {
1520
+ const categorizedRules = rules2 === void 0 ? {} : processCustomRules(rules2);
1521
+ const usingNextjs = isObject(react2) && react2.framework === "next";
1327
1522
  const configs = [
1328
1523
  ignoresConfig({
1329
- next: isObject(react2) && (react2.framework === "next" || react2.next === true),
1524
+ next: usingNextjs,
1330
1525
  storybook,
1331
1526
  userIgnores: ignores
1332
1527
  }),
1333
- baseEslintConfig(functionStyle)
1528
+ baseEslintConfig(
1529
+ functionStyle,
1530
+ Boolean(typescript),
1531
+ categorizedRules[configNames.base]
1532
+ )
1334
1533
  ];
1335
1534
  if (jsdoc2 !== false) {
1336
- configs.push(jsdocConfig(jsdoc2.requireJsdoc ?? false));
1535
+ configs.push(
1536
+ jsdocConfig(
1537
+ jsdoc2.requireJsdoc ?? false,
1538
+ categorizedRules[configNames.jsdoc]
1539
+ )
1540
+ );
1337
1541
  }
1338
1542
  if (typescript) {
1339
1543
  configs.push(
1340
1544
  ...tseslintConfig(
1341
- isString(typescript) ? typescript : void 0
1545
+ isString(typescript) ? typescript : void 0,
1546
+ categorizedRules[configNames.typescript]
1342
1547
  )
1343
1548
  );
1344
1549
  }
1550
+ if (importPlugin) {
1551
+ configs.push(
1552
+ importConfig(Boolean(typescript), categorizedRules[configNames.import])
1553
+ );
1554
+ }
1345
1555
  if (react2) {
1346
- configs.push(reactEslintConfig(functionStyle, Boolean(typescript)));
1347
- const shouldUseReactCompiler = react2 === true || isObject(react2) && react2.reactCompiler !== false;
1348
- if (shouldUseReactCompiler) {
1349
- configs.push(reactCompilerEslintConfig);
1350
- }
1351
- const isNextFramework = isObject(react2) && (react2.framework === "next" || react2.next === true && react2.framework === void 0);
1352
- if (isNextFramework) {
1353
- configs.push(nextjsConfig());
1354
- }
1355
1556
  const shouldUseReactRefresh = (
1356
1557
  // Explicit setting takes precedence
1357
1558
  isObject(react2) && react2.reactRefresh === true || // Framework-based default (vite/none use reactRefresh by default)
1358
1559
  isObject(react2) && (react2.framework === "vite" || react2.framework === "none") && react2.reactRefresh !== false
1359
1560
  );
1360
1561
  if (shouldUseReactRefresh) {
1361
- configs.push(reactRefreshEslintConfig());
1562
+ configs.push(
1563
+ reactRefreshEslintConfig(categorizedRules[configNames.reactRefresh])
1564
+ );
1565
+ }
1566
+ configs.push(
1567
+ reactEslintConfig(
1568
+ functionStyle,
1569
+ Boolean(typescript),
1570
+ categorizedRules[configNames.react]
1571
+ )
1572
+ );
1573
+ const shouldUseReactCompiler = react2 === true || isObject(react2) && react2.reactCompiler !== false;
1574
+ if (shouldUseReactCompiler) {
1575
+ configs.push(
1576
+ reactCompilerEslintConfig(categorizedRules[configNames.reactCompiler])
1577
+ );
1578
+ }
1579
+ if (usingNextjs) {
1580
+ configs.push(nextjsConfig(categorizedRules[configNames.nextjs]));
1362
1581
  }
1363
1582
  }
1364
1583
  if (testing !== false) {
1365
- const defaultTestingConfig = {
1366
- filenamePattern: "test",
1367
- files: ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1368
- formattingRules: true,
1369
- framework: "vitest",
1370
- itOrTest: "it"
1371
- };
1372
- const mergedTestingConfig = {
1373
- ...defaultTestingConfig,
1374
- ...isObject(testing) ? testing : {}
1375
- };
1584
+ const mergedTestingConfig = isObject(testing) ? { ...defaultTestingConfig, ...testing } : defaultTestingConfig;
1376
1585
  const { filenamePattern, files, formattingRules, framework, itOrTest } = mergedTestingConfig;
1377
1586
  configs.push(
1378
- testingConfig({
1379
- filenamePattern,
1380
- files,
1381
- formattingRules,
1382
- framework,
1383
- itOrTest
1384
- })
1587
+ testingConfig(
1588
+ {
1589
+ filenamePattern,
1590
+ files,
1591
+ formattingRules,
1592
+ framework,
1593
+ itOrTest
1594
+ },
1595
+ categorizedRules[configNames.testing]
1596
+ )
1385
1597
  );
1386
1598
  }
1387
1599
  if (sorting) {
1388
- configs.push(perfectionistConfig);
1600
+ configs.push(
1601
+ perfectionistConfig(categorizedRules[configNames.perfectionist])
1602
+ );
1389
1603
  }
1390
1604
  if (unicorn2) {
1391
- configs.push(unicornConfig);
1605
+ configs.push(unicornConfig(categorizedRules[configNames.unicorn]));
1392
1606
  }
1393
1607
  if (functionStyle === "arrow") {
1394
- configs.push(preferArrowFunctionConfig());
1608
+ configs.push(
1609
+ preferArrowFunctionConfig(
1610
+ categorizedRules[configNames.preferArrowFunction]
1611
+ )
1612
+ );
1395
1613
  }
1396
1614
  if (storybook) {
1397
- configs.push(...storybookConfig);
1615
+ configs.push(...storybookConfig(categorizedRules[configNames.storybook]));
1398
1616
  }
1399
1617
  if (turbo2) {
1400
- configs.push(turboConfig());
1618
+ configs.push(turboConfig(categorizedRules[configNames.turbo]));
1401
1619
  }
1402
1620
  if (additionalConfigs.length > 0) {
1403
1621
  configs.push(...additionalConfigs);