@darksheep/eslint 8.0.7 → 9.0.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 (74) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/package.json +8 -3
  3. package/src/configs/eslint-base.js +5 -2
  4. package/src/configs/eslint-complexity.js +4 -1
  5. package/src/configs/eslint-ignores.js +7 -3
  6. package/src/configs/eslint-style.js +6 -3
  7. package/src/configs/react.js +4 -1
  8. package/src/custom-logger/index.js +5 -2
  9. package/src/custom-rules/instance-of-array.js +13 -9
  10. package/src/custom-rules/loose-types.js +8 -4
  11. package/src/custom-rules/no-useless-expression.js +6 -2
  12. package/src/custom-rules/sequence-expression.js +5 -2
  13. package/src/helper/disable-plugin.js +17 -0
  14. package/src/helper/disable-rule.js +17 -0
  15. package/src/helper/edit-rule.js +33 -0
  16. package/src/index.js +11 -4
  17. package/src/plugins/command.js +20 -0
  18. package/src/plugins/eslint-comments.js +4 -1
  19. package/src/plugins/jest.js +135 -0
  20. package/src/plugins/jsdoc.js +23 -3
  21. package/src/plugins/json.js +8 -2
  22. package/src/plugins/node.js +6 -2
  23. package/src/plugins/package-json.js +30 -2
  24. package/src/plugins/perfectionist.js +7 -4
  25. package/src/plugins/promise.js +4 -1
  26. package/src/plugins/react-native.js +4 -1
  27. package/src/plugins/react.js +6 -3
  28. package/src/plugins/regexp.js +4 -1
  29. package/src/plugins/sca.js +4 -1
  30. package/src/plugins/security.js +4 -1
  31. package/src/plugins/style.js +4 -2
  32. package/src/plugins/typescript.js +8 -3
  33. package/src/plugins/unicorn.js +22 -4
  34. package/src/plugins/unused-imports.js +6 -2
  35. package/src/plugins/yml.js +4 -1
  36. package/src/utilities/editorconfig.js +12 -8
  37. package/src/utilities/eslint-files.js +9 -5
  38. package/src/utilities/package.js +6 -2
  39. package/types/src/configs/eslint-base.d.ts +3 -2
  40. package/types/src/configs/eslint-complexity.d.ts +6 -2
  41. package/types/src/configs/eslint-ignores.d.ts +5 -3
  42. package/types/src/configs/eslint-style.d.ts +4 -3
  43. package/types/src/configs/react.d.ts +6 -2
  44. package/types/src/custom-logger/index.d.ts +2 -1
  45. package/types/src/custom-rules/instance-of-array.d.ts +3 -2
  46. package/types/src/custom-rules/loose-types.d.ts +3 -2
  47. package/types/src/custom-rules/no-useless-expression.d.ts +3 -2
  48. package/types/src/custom-rules/sequence-expression.d.ts +6 -2
  49. package/types/src/helper/disable-plugin.d.ts +10 -0
  50. package/types/src/helper/disable-rule.d.ts +10 -0
  51. package/types/src/helper/edit-rule.d.ts +9 -0
  52. package/types/src/index.d.ts +5 -3
  53. package/types/src/plugins/command.d.ts +6 -0
  54. package/types/src/plugins/eslint-comments.d.ts +3 -2
  55. package/types/src/plugins/jest.d.ts +8 -0
  56. package/types/src/plugins/jsdoc.d.ts +3 -2
  57. package/types/src/plugins/json.d.ts +3 -2
  58. package/types/src/plugins/node.d.ts +3 -2
  59. package/types/src/plugins/package-json.d.ts +3 -2
  60. package/types/src/plugins/perfectionist.d.ts +3 -2
  61. package/types/src/plugins/promise.d.ts +3 -2
  62. package/types/src/plugins/react-native.d.ts +3 -2
  63. package/types/src/plugins/react.d.ts +3 -2
  64. package/types/src/plugins/regexp.d.ts +3 -2
  65. package/types/src/plugins/sca.d.ts +3 -2
  66. package/types/src/plugins/security.d.ts +3 -2
  67. package/types/src/plugins/style.d.ts +3 -2
  68. package/types/src/plugins/typescript.d.ts +5 -3
  69. package/types/src/plugins/unicorn.d.ts +3 -2
  70. package/types/src/plugins/unused-imports.d.ts +5 -3
  71. package/types/src/plugins/yml.d.ts +3 -2
  72. package/types/src/utilities/editorconfig.d.ts +4 -3
  73. package/types/src/utilities/eslint-files.d.ts +5 -4
  74. package/types/src/utilities/package.d.ts +5 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [9.0.0](https://github.com/DarkSheepSoftware/eslint/compare/v8.1.0...v9.0.0) (2025-10-10)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * add new rules and plugins ([#1047](https://github.com/DarkSheepSoftware/eslint/issues/1047))
9
+
10
+ ### 🌟 Features
11
+
12
+ * add new rules and plugins ([#1047](https://github.com/DarkSheepSoftware/eslint/issues/1047)) ([ae05958](https://github.com/DarkSheepSoftware/eslint/commit/ae05958b65ff5d7750c402064d3e2f0f683c6737))
13
+
14
+
15
+ ### 📦 Dependencies
16
+
17
+ * **pkg:** pin dependencies ([#1050](https://github.com/DarkSheepSoftware/eslint/issues/1050)) ([91609d1](https://github.com/DarkSheepSoftware/eslint/commit/91609d15085d697fbdddeb4e905b45a3cf371868))
18
+ * **pkg:** update dependency eslint-plugin-jsdoc to v61.1.0 ([#1051](https://github.com/DarkSheepSoftware/eslint/issues/1051)) ([790f781](https://github.com/DarkSheepSoftware/eslint/commit/790f7812aa0b951da19edc3c83726017a19e277a))
19
+
20
+ ## [8.1.0](https://github.com/DarkSheepSoftware/eslint/compare/v8.0.7...v8.1.0) (2025-10-09)
21
+
22
+
23
+ ### 🌟 Features
24
+
25
+ * support node 24 in engines ([5724c9d](https://github.com/DarkSheepSoftware/eslint/commit/5724c9da36bce46e0b319572e5fb63e8ca6d9021))
26
+
3
27
  ## [8.0.7](https://github.com/DarkSheepSoftware/eslint/compare/v8.0.6...v8.0.7) (2025-10-09)
4
28
 
5
29
 
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@darksheep/eslint",
3
- "version": "8.0.7",
3
+ "version": "9.0.0",
4
+ "description": "A fairly complete (opinionated) eslint config",
4
5
  "repository": {
5
6
  "type": "git",
6
7
  "url": "https://github.com/DarkSheepSoftware/eslint"
@@ -19,6 +20,7 @@
19
20
  ],
20
21
  "scripts": {
21
22
  "githooks": "git config core.hooksPath .githooks",
23
+ "inspect": "config-inspector",
22
24
  "prepack": "tsc"
23
25
  },
24
26
  "dependencies": {
@@ -30,7 +32,9 @@
30
32
  "@typescript-eslint/eslint-plugin": "8.46.0",
31
33
  "@typescript-eslint/parser": "8.46.0",
32
34
  "editorconfig": "3.0.1",
33
- "eslint-plugin-jsdoc": "61.0.1",
35
+ "eslint-plugin-command": "3.3.1",
36
+ "eslint-plugin-jest": "29.0.1",
37
+ "eslint-plugin-jsdoc": "61.1.0",
34
38
  "eslint-plugin-jsonc": "2.21.0",
35
39
  "eslint-plugin-n": "17.23.1",
36
40
  "eslint-plugin-package-json": "0.56.3",
@@ -48,6 +52,7 @@
48
52
  },
49
53
  "devDependencies": {
50
54
  "@darksheep/eslint-formatter-github": "2.2.0",
55
+ "@eslint/config-inspector": "~1.3.0",
51
56
  "@types/node": "~22.18.0",
52
57
  "eslint": "~9.37.0",
53
58
  "type-fest": "~5.0.0",
@@ -63,7 +68,7 @@
63
68
  },
64
69
  "packageManager": "yarn@4.10.3",
65
70
  "engines": {
66
- "node": "^20 || ^22"
71
+ "node": "^20.13.1 || >=22.2.0"
67
72
  },
68
73
  "volta": {
69
74
  "node": "22.20.0",
@@ -1,4 +1,7 @@
1
- /** @type {import('eslint').Linter.RulesRecord} */
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
4
+ /** @type {Linter.RulesRecord} */
2
5
  const rules = {
3
6
  'no-else-return': 'error',
4
7
 
@@ -109,7 +112,7 @@ const rules = {
109
112
 
110
113
  /**
111
114
  * Get the ESLint base config.
112
- * @returns {Promise<import('eslint').Linter.Config[]>}
115
+ * @returns {Promise<Linter.Config[]>}
113
116
  */
114
117
  export async function createEslintBaseConfig() {
115
118
  return [ {
@@ -1,6 +1,9 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
1
4
  /**
2
5
  * Get the ESLint config for complexity checks.
3
- * @returns {import('eslint').Linter.Config[]}
6
+ * @returns {Linter.Config[]}
4
7
  */
5
8
  export function createEslintComplexityConfig() {
6
9
  return [ {
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @import { URL } from 'node:url';
3
+ * @import { Linter } from 'eslint';
4
+ */
1
5
  import * as fs from 'node:fs/promises';
2
6
  import { resolve } from 'node:path';
3
7
  import { fileURLToPath } from 'node:url';
@@ -5,7 +9,7 @@ import { fileURLToPath } from 'node:url';
5
9
  import { findUp } from '../utilities/filesystem.js';
6
10
 
7
11
  /**
8
- * @param {import('node:url').URL} root - Root url.
12
+ * @param {URL} root - Root url.
9
13
  * @returns {Promise<string[]>}
10
14
  */
11
15
  async function getGitignore(root) {
@@ -30,8 +34,8 @@ async function getGitignore(root) {
30
34
 
31
35
  /**
32
36
  * Get basic ESLint ignores config.
33
- * @param {import('node:url').URL} root - Root url.
34
- * @returns {Promise<import('eslint').Linter.Config[]>}
37
+ * @param {URL} root - Root url.
38
+ * @returns {Promise<Linter.Config[]>}
35
39
  */
36
40
  export async function createEslintIgnoresConfig(root) {
37
41
  const ignores = await getGitignore(root);
@@ -1,6 +1,9 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
1
4
  import { createEditorOverrides } from '../utilities/editorconfig.js';
2
5
 
3
- /** @type {import('eslint').Linter.RulesRecord} */
6
+ /** @type {Linter.RulesRecord} */
4
7
  const rules = {
5
8
  'dot-notation': 'error',
6
9
  'curly': 'error',
@@ -12,8 +15,8 @@ const rules = {
12
15
 
13
16
  /**
14
17
  * Get basic ESLint style config.
15
- * @param {import('node:url').URL} root - Root url.
16
- * @returns {Promise<import('eslint').Linter.Config[]>}
18
+ * @param {URL} root - Root url.
19
+ * @returns {Promise<Linter.Config[]>}
17
20
  */
18
21
  export async function createStyleConfig(root) {
19
22
  return [
@@ -1,6 +1,9 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
1
4
  /**
2
5
  * Get basic ESLint style config.
3
- * @returns {Promise<import('eslint').Linter.Config[]>}
6
+ * @returns {Promise<Linter.Config[]>}
4
7
  */
5
8
  export async function createReactConfig() {
6
9
  return [
@@ -1,9 +1,12 @@
1
+ /**
2
+ * @import { ESLint, Linter } from 'eslint';
3
+ */
1
4
  import { relative } from 'node:path';
2
5
 
3
6
  import { getEnvString } from '@darksheep/environment';
4
7
 
5
8
  /**
6
- * @param {import('eslint').Linter.LintMessage[][]} files - Some messages.
9
+ * @param {Linter.LintMessage[][]} files - Some messages.
7
10
  * @returns {number}
8
11
  */
9
12
  function getSeverity(files) {
@@ -58,7 +61,7 @@ const icons = [
58
61
 
59
62
  /** @type {Set<string>} */
60
63
  const files = new Set();
61
- /** @type {import('eslint').ESLint.Plugin} */
64
+ /** @type {ESLint.Plugin} */
62
65
  export default {
63
66
  processors: {
64
67
  logger: {
@@ -1,10 +1,14 @@
1
1
  /**
2
- * @param {import('eslint').Rule.RuleContext} context - ESLint rule context.
3
- * @returns {import('eslint').Rule.RuleListener}
2
+ * @import { Rule } from 'eslint';
3
+ */
4
+
5
+ /**
6
+ * @param {Rule.RuleContext} context - ESLint rule context.
7
+ * @returns {Rule.RuleListener}
4
8
  */
5
9
  const preferInstance = (context) => ({
6
10
  /**
7
- * @param {import('eslint').Rule.Node} node - The AST function node.
11
+ * @param {Rule.Node} node - The AST function node.
8
12
  * @returns {void}
9
13
  */
10
14
  'CallExpression[callee.object.name = "Array"][callee.property.name = "isArray"]': (node) => {
@@ -19,7 +23,7 @@ const preferInstance = (context) => ({
19
23
  }
20
24
 
21
25
  const left = context.sourceCode.getText(node.arguments[0]);
22
- /** @type {import('eslint').Rule.ReportFixer} */
26
+ /** @type {Rule.ReportFixer} */
23
27
  const fix = (fixer) => fixer.replaceText(node, `${left} instanceof Array`);
24
28
 
25
29
  context.report({ node, message, fix });
@@ -27,12 +31,12 @@ const preferInstance = (context) => ({
27
31
  });
28
32
 
29
33
  /**
30
- * @param {import('eslint').Rule.RuleContext} context - ESLint rule context.
31
- * @returns {import('eslint').Rule.RuleListener}
34
+ * @param {Rule.RuleContext} context - ESLint rule context.
35
+ * @returns {Rule.RuleListener}
32
36
  */
33
37
  const preferIsArray = (context) => ({
34
38
  /**
35
- * @param {import('eslint').Rule.Node} node - The AST function node.
39
+ * @param {Rule.Node} node - The AST function node.
36
40
  * @returns {void}
37
41
  */
38
42
  'BinaryExpression[operator="instanceof"][right.type="Identifier"][right.name="Array"]': (node) => {
@@ -43,14 +47,14 @@ const preferIsArray = (context) => ({
43
47
  const message = 'Use `Array.isArray()` instead of `instanceof Array`';
44
48
 
45
49
  const argument = context.sourceCode.getText(node.left);
46
- /** @type {import('eslint').Rule.ReportFixer} */
50
+ /** @type {Rule.ReportFixer} */
47
51
  const fix = (fixer) => fixer.replaceText(node, `Array.isArray(${argument})`);
48
52
 
49
53
  context.report({ node, message, fix });
50
54
  },
51
55
  });
52
56
 
53
- /** @type {import('eslint').Rule.RuleModule} */
57
+ /** @type {Rule.RuleModule} */
54
58
  const rule = {
55
59
  meta: {
56
60
  type: 'suggestion',
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @import { Rule } from 'eslint';
3
+ */
4
+
1
5
  /**
2
6
  * @param {unknown} input - The possible object.
3
7
  * @returns {input is { [key: string]: unknown }}
@@ -8,15 +12,15 @@ function isObject(input) {
8
12
 
9
13
  /**
10
14
  * @param {string} optionName - Name of the property option.
11
- * @param {import('eslint').Rule.RuleContext} context - ESLint rule context.
15
+ * @param {Rule.RuleContext} context - ESLint rule context.
12
16
  * @param {string} message - Error message on report.
13
- * @returns {(node: import('eslint').Rule.Node) => void}
17
+ * @returns {(node: Rule.Node) => void}
14
18
  */
15
19
  function createReporter(optionName, context, message) {
16
20
  const [ options ] = context.options;
17
21
 
18
22
  /**
19
- * @param {import('eslint').Rule.Node} node - The AST function node.
23
+ * @param {Rule.Node} node - The AST function node.
20
24
  * @returns {void}
21
25
  */
22
26
  function validateNode(node) {
@@ -31,7 +35,7 @@ function createReporter(optionName, context, message) {
31
35
  return validateNode;
32
36
  }
33
37
 
34
- /** @type {import('eslint').Rule.RuleModule} */
38
+ /** @type {Rule.RuleModule} */
35
39
  const rule = {
36
40
  meta: {
37
41
  type: 'problem',
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @import { Rule } from 'eslint';
3
+ */
4
+
1
5
  const selector = [
2
6
  // test || false, false || test
3
7
  'LogicalExpression[operator="||"] > [type=/Literal$/]',
@@ -5,14 +9,14 @@ const selector = [
5
9
  'LogicalExpression[operator="&&"] > [type=/Literal$/]',
6
10
  ].join(', ');
7
11
 
8
- /** @type {import('eslint').Rule.RuleModule} */
12
+ /** @type {Rule.RuleModule} */
9
13
  const rule = {
10
14
  meta: { type: 'suggestion' },
11
15
 
12
16
  create: function (context) {
13
17
  return {
14
18
  /**
15
- * @param {import('eslint').Rule.Node} node - The AST function node.
19
+ * @param {Rule.Node} node - The AST function node.
16
20
  * @returns {void}
17
21
  */
18
22
  [selector]: (node) => {
@@ -1,11 +1,14 @@
1
- /** @type {import('eslint').Rule.RuleModule} */
1
+ /**
2
+ * @import { Rule } from 'eslint';
3
+ */
4
+ /** @type {Rule.RuleModule} */
2
5
  const rule = {
3
6
  meta: { type: 'suggestion' },
4
7
 
5
8
  create: function (context) {
6
9
  return {
7
10
  /**
8
- * @param {import('eslint').Rule.Node} node - The AST function node.
11
+ * @param {Rule.Node} node - The AST function node.
9
12
  * @returns {void}
10
13
  */
11
14
  SequenceExpression: (node) => {
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @import { Linter } from 'eslint'
3
+ */
4
+
5
+ /**
6
+ * @param {string} plugin - The name of the plugin.
7
+ * @param {Linter.Config[]} configs - The name of the rule.
8
+ * @returns {void}
9
+ */
10
+ export function disablePlugin(plugin, configs) {
11
+ for (let i = configs.length - 1; i >= 0; i--) {
12
+ const config = configs[i];
13
+ if (config?.plugins?.[plugin] != null) {
14
+ configs.splice(i, 1);
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @import { Linter } from 'eslint'
3
+ */
4
+
5
+ /**
6
+ * @param {string} rule - The name of the rule.
7
+ * @param {Linter.Config[]} configs - The name of the rule.
8
+ * @returns {void}
9
+ */
10
+ export function disableRule(rule, configs) {
11
+ for (let i = configs.length - 1; i >= 0; i--) {
12
+ const config = configs[i];
13
+ if (config?.rules?.[rule] != null) {
14
+ config.rules[rule] = 0;
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @import { Linter } from 'eslint'
3
+ */
4
+
5
+ /**
6
+ * @param {Linter.RuleEntry} rule - The original rule.
7
+ * @returns {Linter.RuleSeverity}
8
+ */
9
+ function getCurrentSeverity(rule) {
10
+ if (typeof rule === 'string' || typeof rule === 'number') {
11
+ return rule;
12
+ }
13
+
14
+ return rule[0];
15
+ }
16
+
17
+ /**
18
+ * @param {Linter.Config[]} configs - The name of the rule.
19
+ * @param {string} rule - The name of the rule.
20
+ * @param {Linter.RuleSeverity | undefined} severity - The new severity.
21
+ * @param {unknown} [options] - Additional options for the rule.
22
+ * @returns {void}
23
+ */
24
+ export function editRule(configs, rule, severity, options) {
25
+ for (const config of configs) {
26
+ if (config?.rules?.[rule] != null) {
27
+ config.rules[rule] = [
28
+ severity ?? getCurrentSeverity(config.rules[rule]),
29
+ options,
30
+ ];
31
+ }
32
+ }
33
+ }
package/src/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
1
4
  import { pathToFileURL, URL } from 'node:url';
2
5
 
3
6
  import { createEslintBaseConfig } from './configs/eslint-base.js';
@@ -6,7 +9,9 @@ import { createEslintIgnoresConfig } from './configs/eslint-ignores.js';
6
9
  import { createEslintRecommendsConfig } from './configs/eslint-recommended.js';
7
10
  import { createStyleConfig } from './configs/eslint-style.js';
8
11
  import { createReactConfig } from './configs/react.js';
12
+ import { createEslintCommandConfig } from './plugins/command.js';
9
13
  import { createEslintCommentsConfig } from './plugins/eslint-comments.js';
14
+ import { createEslintJestConfig } from './plugins/jest.js';
10
15
  import { createEslintJSDocConfig } from './plugins/jsdoc.js';
11
16
  import { createEslintJsonConfig } from './plugins/json.js';
12
17
  import { createEslintNodeConfig } from './plugins/node.js';
@@ -30,10 +35,12 @@ const configBuilders = [
30
35
  createEslintBaseConfig,
31
36
  createEslintComplexityConfig,
32
37
  createStyleConfig,
38
+ createEslintCommandConfig,
33
39
  createEslintCommentsConfig,
34
40
  createEslintNodeConfig,
35
41
  createEslintPerfectionistConfig,
36
42
  createEslintPackageJsonConfig,
43
+ createEslintJestConfig,
37
44
  createEslintJsonConfig,
38
45
  createEslintYmlConfig,
39
46
  createEslintPromiseConfig,
@@ -51,8 +58,8 @@ const configBuilders = [
51
58
  ];
52
59
 
53
60
  /**
54
- * @param {import('node:url').URL} root - The root url object for the project config.
55
- * @returns {Promise<import('eslint').Linter.Config[]>}
61
+ * @param {URL} root - The root url object for the project config.
62
+ * @returns {Promise<Linter.Config[]>}
56
63
  */
57
64
  async function createConfigUrl(root) {
58
65
  const configs = await Promise.all(
@@ -63,8 +70,8 @@ async function createConfigUrl(root) {
63
70
  }
64
71
 
65
72
  /**
66
- * @param {string | import('node:url').URL} root - Root url.
67
- * @returns {Promise<import('eslint').Linter.Config[]>}
73
+ * @param {string | URL} root - Root url.
74
+ * @returns {Promise<Linter.Config[]>}
68
75
  */
69
76
  export async function createConfig(root) {
70
77
  if (root instanceof URL) {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
4
+ import command from 'eslint-plugin-command';
5
+
6
+ /**
7
+ * Get ESLint config for the node plugin.
8
+ * @returns {Promise<Linter.Config[]>}
9
+ */
10
+ export async function createEslintCommandConfig() {
11
+ return [
12
+ {
13
+ name: 'command/common',
14
+ plugins: { command },
15
+ rules: {
16
+ 'command/command': 'error',
17
+ },
18
+ },
19
+ ];
20
+ }
@@ -1,8 +1,11 @@
1
+ /**
2
+ * @import { Linter } from 'eslint';
3
+ */
1
4
  import eslintComments from '@eslint-community/eslint-plugin-eslint-comments';
2
5
 
3
6
  /**
4
7
  * Get ESLint config for comments check.
5
- * @returns {import('eslint').Linter.Config[]}
8
+ * @returns {Linter.Config[]}
6
9
  */
7
10
  export function createEslintCommentsConfig() {
8
11
  return [
@@ -0,0 +1,135 @@
1
+ import { getTypescriptFiles } from '../utilities/eslint-files.js';
2
+ /**
3
+ * @import { URL } from 'node:url';
4
+ * @import { Linter } from 'eslint';
5
+ */
6
+ import { getPackageJson } from '../utilities/package.js';
7
+
8
+ /**
9
+ * @template {Object} T
10
+ * @param {T | { default: T }} target - The module to optionally check for default exports.
11
+ * @returns {T}
12
+ */
13
+ function idef(target) {
14
+ return /** @type {{ default: T }} */ (target)?.default ?? target;
15
+ }
16
+
17
+ /**
18
+ * Get ESLint config for the typescript plugin.
19
+ * @param {URL} root - Root url.
20
+ * @returns {Promise<Linter.Config[]>}
21
+ */
22
+ export async function createEslintJestConfig(root) {
23
+ const packageJson = await getPackageJson(root, 'jest');
24
+ if (packageJson == null) {
25
+ return [];
26
+ }
27
+
28
+ const jest = idef(await import('eslint-plugin-jest'));
29
+
30
+ return [
31
+ {
32
+ name: 'jest/base',
33
+ files: [
34
+ '**/test/**',
35
+ '**/spec/**',
36
+ '**/__mocks__/**',
37
+ '**/{test,spec,jest}.{js,ts}',
38
+ '**/*.{test,spec}.{js,ts}',
39
+ ],
40
+ plugins: { jest },
41
+ languageOptions: {
42
+ globals: jest.environments.globals.globals,
43
+ },
44
+ settings: {
45
+ jest: {
46
+ version: packageJson.version,
47
+ },
48
+ },
49
+
50
+ rules: {
51
+ 'max-lines': 'off',
52
+ 'max-lines-per-function': 'off',
53
+ 'max-nested-callbacks': 'off',
54
+ 'max-params': 'off',
55
+
56
+ 'n/global-require': 'off',
57
+ 'global-require': 'off',
58
+
59
+ 'jest/consistent-test-it': [ 'error', { fn: 'test', withinDescribe: 'test' } ],
60
+ 'jest/expect-expect': [ 'error', { assertFunctionNames: [ 'expect' ] } ],
61
+ 'jest/max-expects': 'off',
62
+ 'jest/max-nested-describe': 'off',
63
+ 'jest/no-alias-methods': 'error',
64
+ 'jest/no-commented-out-tests': 'error',
65
+ 'jest/no-conditional-expect': 'error',
66
+ 'jest/no-conditional-in-test': 'warn',
67
+ 'jest/no-confusing-set-timeout': 'warn',
68
+ 'jest/no-deprecated-functions': 'error',
69
+ 'jest/no-disabled-tests': 'warn',
70
+ 'jest/no-done-callback': 'error',
71
+ 'jest/no-duplicate-hooks': 'error',
72
+ 'jest/no-export': 'error',
73
+ 'jest/no-focused-tests': 'warn',
74
+ 'jest/no-hooks': 'off',
75
+ 'jest/no-identical-title': 'error',
76
+ 'jest/no-interpolation-in-snapshots': 'off',
77
+ 'jest/no-jasmine-globals': 'error',
78
+ 'jest/no-large-snapshots': 'off',
79
+ 'jest/no-mocks-import': 'error',
80
+ 'jest/no-restricted-jest-methods': 'off',
81
+ 'jest/no-restricted-matchers': 'off',
82
+ 'jest/no-standalone-expect': 'error',
83
+ 'jest/no-test-prefixes': 'error',
84
+ 'jest/no-test-return-statement': 'error',
85
+ 'jest/prefer-called-with': 'warn',
86
+ 'jest/prefer-comparison-matcher': 'warn',
87
+ 'jest/prefer-each': 'warn',
88
+ 'jest/prefer-ending-with-an-expect': 'off',
89
+ 'jest/prefer-equality-matcher': 'warn',
90
+ 'jest/prefer-expect-assertions': [ 'warn', { onlyFunctionsWithAsyncKeyword: true } ],
91
+ 'jest/prefer-expect-resolves': 'warn',
92
+ 'jest/prefer-hooks-in-order': 'warn',
93
+ 'jest/prefer-hooks-on-top': 'warn',
94
+ 'jest/prefer-importing-jest-globals': 'off',
95
+ 'jest/prefer-jest-mocked': 'error',
96
+ 'jest/prefer-lowercase-title': 'off',
97
+ 'jest/prefer-mock-promise-shorthand': 'warn',
98
+ 'jest/prefer-snapshot-hint': 'off',
99
+ 'jest/prefer-spy-on': 'warn',
100
+ 'jest/prefer-strict-equal': 'error',
101
+ 'jest/prefer-to-be': 'warn',
102
+ 'jest/prefer-to-contain': 'warn',
103
+ 'jest/prefer-to-have-length': 'warn',
104
+ 'jest/prefer-todo': 'warn',
105
+ 'jest/require-hook': 'warn',
106
+ 'jest/require-to-throw-message': 'error',
107
+ 'jest/require-top-level-describe': 'error',
108
+ 'jest/unbound-method': 'off',
109
+ 'jest/valid-describe-callback': 'error',
110
+ 'jest/valid-expect-in-promise': 'error',
111
+ 'jest/valid-expect': 'error',
112
+ 'jest/valid-title': 'error',
113
+
114
+ // Jest style
115
+
116
+ 'jest/padding-around-after-all-blocks': 'off',
117
+ 'jest/padding-around-after-each-blocks': 'off',
118
+ 'jest/padding-around-all': 'off',
119
+ 'jest/padding-around-before-all-blocks': 'off',
120
+ 'jest/padding-around-before-each-blocks': 'off',
121
+ 'jest/padding-around-describe-blocks': 'off',
122
+ 'jest/padding-around-expect-groups': 'off',
123
+ 'jest/padding-around-test-blocks': 'off',
124
+ },
125
+ },
126
+ {
127
+ name: 'jest/typescript',
128
+ files: getTypescriptFiles(),
129
+ plugins: { jest },
130
+ rules: {
131
+ 'jest/no-untyped-mock-factory': 'warn',
132
+ },
133
+ },
134
+ ];
135
+ }