eslint-config-agent 3.0.4 → 3.1.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/CHANGELOG.md +158 -0
- package/README.md +592 -26
- package/configs/base-plugins.js +32 -0
- package/configs/config-files.js +19 -3
- package/configs/examples.js +12 -1
- package/configs/javascript.js +12 -4
- package/configs/length-rule-scope.js +27 -0
- package/configs/overrides.js +3 -14
- package/configs/test-files.js +40 -1
- package/configs/tsx.js +10 -0
- package/configs/typescript.js +44 -2
- package/exports/ddd.d.ts +10 -0
- package/exports/ddd.js +1 -3
- package/exports/incremental.d.ts +11 -0
- package/exports/incremental.js +39 -0
- package/exports/recommended-incremental.d.ts +11 -0
- package/exports/recommended-incremental.js +46 -0
- package/exports/recommended.d.ts +14 -0
- package/exports/recommended.js +110 -0
- package/exports/to-warnings.d.ts +20 -0
- package/exports/to-warnings.js +41 -0
- package/index.d.ts +18 -0
- package/index.js +883 -7
- package/package.json +46 -17
- package/plugins/index.js +6 -0
- package/rules/index.js +20 -22
- package/rules/no-inline-union-types/index.js +8 -6
- package/rules/no-process-env-properties/index.js +4 -4
- package/rules/no-record-literal-types/index.js +3 -3
- package/rules/plugin/import/index.js +41 -0
- package/rules/plugin/index.js +0 -2
- package/rules/plugin/n/index.js +16 -2
- package/rules/plugin/n/no-process-env/index.js +4 -4
- package/rules/plugin/react/index.js +150 -2
- package/rules/plugin/typescript-eslint/index.js +406 -0
- package/rules/require-spec-file-tsx/README.md +57 -0
- package/rules/require-spec-file-tsx/helpers.js +93 -0
- package/rules/require-spec-file-tsx/index.js +109 -0
- package/rules/plugin/jsx-a11y/index.js +0 -3
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom ESLint rule: require-spec-file-tsx
|
|
3
|
+
*
|
|
4
|
+
* Require a sibling spec/test file next to every `.tsx`/`.jsx` source file
|
|
5
|
+
* that contains logic (a component, hook, or any function/class with a body).
|
|
6
|
+
*
|
|
7
|
+
* Why this rule exists: the shared config already enforces
|
|
8
|
+
* `ddd/require-spec-file`, but the upstream `eslint-plugin-ddd` rule only
|
|
9
|
+
* inspects `.js`/`.ts` files — it bails out on any other extension. That
|
|
10
|
+
* silently exempts `.tsx`/`.jsx` files, i.e. the React/Preact components this
|
|
11
|
+
* config primarily targets. This rule covers the JSX extensions with the same
|
|
12
|
+
* heuristic, leaving `.js`/`.ts` to the `ddd` plugin.
|
|
13
|
+
*
|
|
14
|
+
* A file satisfies the rule when a sibling `<name>.spec.<ext>` exists in the
|
|
15
|
+
* same directory. As with `ddd/require-spec-file`, only the `.spec.*` name
|
|
16
|
+
* counts; a `.test.*` sibling is still skipped from needing its own spec but
|
|
17
|
+
* does not satisfy the requirement for the source file.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { existsSync } from 'node:fs'
|
|
21
|
+
import { parse as parsePath, join as joinPath } from 'node:path'
|
|
22
|
+
import {
|
|
23
|
+
JSX_EXTENSIONS,
|
|
24
|
+
hasLogicInNode,
|
|
25
|
+
checkExcludePatterns,
|
|
26
|
+
DEFAULT_EXCLUDE_PATTERNS,
|
|
27
|
+
} from './helpers.js'
|
|
28
|
+
|
|
29
|
+
export const requireSpecFileTsxRule = {
|
|
30
|
+
meta: {
|
|
31
|
+
type: 'problem',
|
|
32
|
+
docs: {
|
|
33
|
+
description:
|
|
34
|
+
'Require a sibling spec/test file for .tsx/.jsx files with logic',
|
|
35
|
+
category: 'Best Practices',
|
|
36
|
+
},
|
|
37
|
+
messages: {
|
|
38
|
+
missingSpecFile:
|
|
39
|
+
'Missing spec file: "{{specFile}}" should exist alongside this file.',
|
|
40
|
+
},
|
|
41
|
+
schema: [
|
|
42
|
+
{
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
excludePatterns: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
items: { type: 'string' },
|
|
48
|
+
description:
|
|
49
|
+
'Glob patterns to exclude from the spec-file requirement',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
additionalProperties: false,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
create(context) {
|
|
58
|
+
const options = context.options[0] || {}
|
|
59
|
+
const excludePatterns = options.excludePatterns || DEFAULT_EXCLUDE_PATTERNS
|
|
60
|
+
|
|
61
|
+
let hasLogic = false
|
|
62
|
+
const markLogic = node => {
|
|
63
|
+
if (hasLogicInNode(node)) {
|
|
64
|
+
hasLogic = true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
FunctionDeclaration: markLogic,
|
|
70
|
+
FunctionExpression: markLogic,
|
|
71
|
+
ArrowFunctionExpression: markLogic,
|
|
72
|
+
ClassDeclaration: markLogic,
|
|
73
|
+
ClassExpression: markLogic,
|
|
74
|
+
|
|
75
|
+
'Program:exit'(node) {
|
|
76
|
+
const filename = context.filename || context.getFilename()
|
|
77
|
+
const normalized = filename.replaceAll('\\', '/')
|
|
78
|
+
const parsed = parsePath(normalized)
|
|
79
|
+
const extension = JSX_EXTENSIONS.find(candidate =>
|
|
80
|
+
normalized.endsWith(candidate)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if (!extension) {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
// A spec/test file never needs its own spec.
|
|
87
|
+
if (parsed.name.endsWith('.spec') || parsed.name.endsWith('.test')) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
if (!hasLogic || checkExcludePatterns(normalized, excludePatterns)) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const specFileName = `${parsed.name}.spec${extension}`
|
|
95
|
+
const hasSibling = existsSync(joinPath(parsed.dir, specFileName))
|
|
96
|
+
|
|
97
|
+
if (!hasSibling) {
|
|
98
|
+
context.report({
|
|
99
|
+
node,
|
|
100
|
+
messageId: 'missingSpecFile',
|
|
101
|
+
data: { specFile: specFileName },
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default requireSpecFileTsxRule
|