eslint-config-agent 3.0.3 → 3.0.5

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.
@@ -46,6 +46,37 @@ export const basePluginsConfig = [
46
46
  ],
47
47
  },
48
48
  },
49
+ // Require spec files for .tsx/.jsx source files too.
50
+ //
51
+ // `ddd/require-spec-file` only inspects `.js`/`.ts` files, so React/Preact
52
+ // components — the code this config primarily targets — were silently exempt
53
+ // from the spec requirement. This custom rule covers the JSX extensions with
54
+ // the same heuristic, completing the "spec file for every source file"
55
+ // promise. Its excludePatterns mirror the JSX-relevant entries of the `ddd`
56
+ // list above (index/stories files are exempt; the error/exception file
57
+ // patterns are exempt; `.spec`/`.test` files are skipped by the rule
58
+ // itself).
59
+ {
60
+ rules: {
61
+ 'custom/require-spec-file-tsx': [
62
+ 'error',
63
+ {
64
+ excludePatterns: [
65
+ '**/index.tsx',
66
+ '**/index.jsx',
67
+ '**/*.stories.{tsx,jsx}',
68
+ // Mirror the ddd error/exception exemptions for JSX extensions so
69
+ // an error component (e.g. an error boundary) is not singled out
70
+ // for a spec file when its `.ts` equivalent is exempt.
71
+ '**/*-error.{tsx,jsx}',
72
+ '**/*.error.{tsx,jsx}',
73
+ '**/errors/**',
74
+ '**/exceptions/**',
75
+ ],
76
+ },
77
+ ],
78
+ },
79
+ },
49
80
  // Disable DDD for config infrastructure files
50
81
  {
51
82
  files: [
@@ -60,6 +91,7 @@ export const basePluginsConfig = [
60
91
  ],
61
92
  rules: {
62
93
  'ddd/require-spec-file': 'off',
94
+ 'custom/require-spec-file-tsx': 'off',
63
95
  },
64
96
  },
65
97
  ]
@@ -1,16 +1,32 @@
1
1
  /**
2
2
  * Configuration for configuration files
3
3
  * Allows hardcoded values and default exports in config files
4
+ *
5
+ * The `*.config.*` and `eslint.config.*` globs are recursive (they are
6
+ * prefixed with a globstar) so the relaxations also reach config files that
7
+ * live below the repo root — e.g. `apps/web/vite.config.ts` or
8
+ * `packages/ui/eslint.config.mjs` in a monorepo. Previously these used
9
+ * root-only globs (`*.config.{...}`), so a nested `eslint.config.mjs` /
10
+ * `vite.config.ts` silently escaped the config-file relaxations and got hit
11
+ * with `default/no-localhost`, `default/no-hardcoded-urls`, `max-lines`, etc.
12
+ * — the same asymmetry the `.mjs`/`.cjs` coverage fix addressed for the
13
+ * JavaScript rule set. This now mirrors the recursive-glob convention every
14
+ * other config block already uses.
15
+ *
16
+ * `index.js` is intentionally left root-scoped: broadening it to a recursive
17
+ * glob would relax these rules for every barrel/entry file in a consumer's
18
+ * source tree, masking real issues. Only files whose names mark them as
19
+ * configuration (`*.config.*`, `eslint.config.*`) are matched recursively.
4
20
  */
5
21
 
6
22
  export const configFilesConfig = [
7
23
  // Configuration files - allow hardcoded values for configuration purposes
8
24
  {
9
25
  files: [
10
- '*.config.{js,ts}',
11
- 'eslint.config.{js,ts}',
26
+ '**/*.config.{js,ts,mjs,cjs}',
27
+ '**/eslint.config.{js,ts,mjs,cjs}',
12
28
  'index.js',
13
- '**/configs/**/*.{js,ts}',
29
+ '**/configs/**/*.{js,ts,mjs,cjs}',
14
30
  ],
15
31
  rules: {
16
32
  'default/no-localhost': 'off',
@@ -45,7 +45,7 @@ const sharedRestrictedSyntax = [
45
45
  message:
46
46
  'Exporting from external libraries is not allowed. Only re-export from relative paths or scoped packages.',
47
47
  },
48
- allRules.noProcessEnvPropertiesConfig,
48
+ allRules.noProcessEnvironmentPropertiesConfig,
49
49
  allRules.noExportSpecifiersConfig,
50
50
  ...allRules.noDefaultClassExportRules,
51
51
  ]
@@ -83,10 +83,21 @@ export const examplesConfig = [
83
83
  // Relax file/function length limits for concise examples
84
84
  'max-lines-per-function': 'off',
85
85
  'max-lines': 'off',
86
+ // Example fixtures demonstrate rule behavior and use `console.log` as
87
+ // illustrative sample code, so the shared `no-console` ban does not apply.
88
+ 'no-console': 'off',
86
89
  // Examples don't need JSDoc
87
90
  'jsdoc/require-jsdoc': 'off',
88
91
  'jsdoc/require-param': 'off',
89
92
  'jsdoc/require-returns': 'off',
90
93
  },
91
94
  },
95
+ {
96
+ // JavaScript example fixtures (the `.ts` block above only matches `.ts`).
97
+ // They likewise use `console.log` as sample code.
98
+ files: ['**/rules/**/examples/**/*.js'],
99
+ rules: {
100
+ 'no-console': 'off',
101
+ },
102
+ },
92
103
  ]
@@ -1,8 +1,14 @@
1
1
  /**
2
2
  * JavaScript File Configurations
3
3
  *
4
- * Handles all JavaScript (.js) file-specific rules.
4
+ * Handles all JavaScript (.js, .mjs, .cjs) file-specific rules.
5
5
  * Plugin registration removed - all plugins registered globally in index.js.
6
+ *
7
+ * The ESM/CommonJS extensions (`.mjs`/`.cjs`) are linted with the same rule set
8
+ * as plain `.js`, mirroring how the TypeScript config covers `.mts`/`.cts`
9
+ * alongside `.ts`. Previously these were ignored here, so `.mjs`/`.cjs` source
10
+ * files silently escaped the package's signature `no-restricted-syntax`,
11
+ * `single-export`, and `required-exports` rules.
6
12
  */
7
13
 
8
14
  import globals from 'globals'
@@ -10,15 +16,13 @@ import globals from 'globals'
10
16
  export const javascriptConfig = (sharedRules, sharedRestrictedSyntax) => [
11
17
  // JavaScript files (not JSX)
12
18
  {
13
- files: ['**/*.js'],
19
+ files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
14
20
  ignores: [
15
21
  '**/node_modules/**',
16
22
  '**/dist/**',
17
23
  '**/build/**',
18
24
  'pnpm-lock.yaml',
19
25
  '**/*.umd.js',
20
- '**/*.cjs',
21
- '**/*.mjs',
22
26
  '**/*.stories.{js,jsx,ts,tsx}',
23
27
  '**/rules/**/index.js',
24
28
  ],
@@ -70,6 +74,10 @@ export const javascriptConfig = (sharedRules, sharedRestrictedSyntax) => [
70
74
  },
71
75
  rules: {
72
76
  ...sharedRules,
77
+ // Build/CI tooling under `scripts/` is a console program: printing to
78
+ // stdout is its job, so the shared `no-console` ban (aimed at leftover
79
+ // debugging in shipped source) does not apply here.
80
+ 'no-console': 'off',
73
81
  'no-restricted-syntax': ['error', ...sharedRestrictedSyntax],
74
82
  },
75
83
  },
@@ -79,7 +79,7 @@ export const overridesConfig = (
79
79
  'Type assertions with indexed access types like "as (typeof X)[number]" are not allowed. Use a named type instead.',
80
80
  },
81
81
  allRules.noTypeAssertionsConfig,
82
- allRules.noProcessEnvPropertiesConfig,
82
+ allRules.noProcessEnvironmentPropertiesConfig,
83
83
  allRules.noExportSpecifiersConfig,
84
84
  ],
85
85
  },
@@ -58,7 +58,7 @@ const sharedRestrictedSyntax = [
58
58
  message:
59
59
  'Exporting from external libraries is not allowed. Only re-export from relative paths or scoped packages.',
60
60
  },
61
- allRules.noProcessEnvPropertiesConfig,
61
+ allRules.noProcessEnvironmentPropertiesConfig,
62
62
  allRules.noExportSpecifiersConfig,
63
63
  ...allRules.noDefaultClassExportRules,
64
64
  ]
@@ -101,13 +101,49 @@ export const testFilesConfig = [
101
101
  rules: {
102
102
  'max-lines-per-function': 'off',
103
103
  'max-lines': 'off', // Ignore file length limits in test and spec files
104
+ // The shared config bans bare `console.log` in shipped source, but test
105
+ // and rule-tester spec files use `console.log` legitimately to report
106
+ // progress and assertions (this package's own `*.test.js` runners do
107
+ // exactly that), and fixtures embed it as sample code. Keep the rule on
108
+ // for real source and off here so test logging is not flagged.
109
+ 'no-console': 'off',
104
110
  'default/no-localhost': ['error', { allowInTests: true }],
105
111
  'default/no-hardcoded-urls': ['error', { allowInTests: true }],
106
112
  'default/no-default-params': 'off', // Allow default parameters in test files for demonstration purposes
113
+ // Test and rule-tester spec files routinely embed source snippets inside
114
+ // string literals as fixtures (e.g. `code: 'const x = `${y}`'`), where a
115
+ // literal `${...}` is the intended payload, not a mis-quoted template.
116
+ // Keep no-template-curly-in-string on for real source but off here so the
117
+ // fixtures are not flagged.
118
+ 'no-template-curly-in-string': 'off',
107
119
  // Disable error plugin rules in test files
108
120
  'error/no-generic-error': 'off',
109
121
  'error/require-custom-error': 'off',
110
122
  'error/no-throw-literal': 'off',
123
+ // Relax the noisy `eslint-plugin-security` heuristics for test code.
124
+ //
125
+ // These rules exist to harden *shipped* code against attacker-controlled
126
+ // input, but their detection is purely syntactic and fires constantly on
127
+ // perfectly safe test setup: a fixture path built from a temp dir
128
+ // (`detect-non-literal-fs-filename`), indexing a lookup table by a loop
129
+ // variable (`detect-object-injection`), compiling a pattern from a test
130
+ // input (`detect-non-literal-regexp`), spawning a helper binary in an
131
+ // integration test (`detect-child-process`), or `require`-ing a module
132
+ // resolved at runtime in a fixture loader (`detect-non-literal-require`).
133
+ // None of these are vulnerabilities in test files — the inputs are the
134
+ // test's own literals, not untrusted data, and the code never reaches
135
+ // production — so they are false positives that force adopters to litter
136
+ // specs with `eslint-disable` comments (this package's own
137
+ // `scripts/test-runner.js` already does exactly that). Turning them off
138
+ // for tests mirrors the `error/*` relaxations above; the genuinely
139
+ // value-adding security rules (`detect-unsafe-regex` for ReDoS,
140
+ // `detect-eval-with-expression`, `detect-buffer-noassert`, the timing and
141
+ // bidi-character checks) stay enabled everywhere.
142
+ 'security/detect-non-literal-fs-filename': 'off',
143
+ 'security/detect-object-injection': 'off',
144
+ 'security/detect-non-literal-regexp': 'off',
145
+ 'security/detect-child-process': 'off',
146
+ 'security/detect-non-literal-require': 'off',
111
147
  // Allow multiple exports in test files for testing import/export patterns
112
148
  'no-restricted-syntax': [
113
149
  'warn',
@@ -204,6 +240,9 @@ export const testFilesConfig = [
204
240
  'jsdoc/require-jsdoc': 'off',
205
241
  'jsdoc/require-param': 'off',
206
242
  'jsdoc/require-returns': 'off',
243
+ // Spec files act as CLI test runners and legitimately call process.exit()
244
+ // to report pass/fail status — the unicorn rule is for library code only.
245
+ 'unicorn/no-process-exit': 'off',
207
246
  },
208
247
  },
209
248
 
package/configs/tsx.js CHANGED
@@ -30,9 +30,19 @@ export const tsxConfig = (
30
30
  },
31
31
  },
32
32
  settings: {
33
+ react: {
34
+ version: 'detect',
35
+ },
33
36
  'import/resolver': {
34
37
  typescript: {},
35
38
  },
39
+ // Tell eslint-plugin-import to parse TypeScript dependency files with the
40
+ // TS parser. Without this, the resolver finds the file but the plugin
41
+ // cannot read its imports/exports, so cross-file rules like
42
+ // import/no-cycle silently never fire on .ts/.tsx code.
43
+ 'import/parsers': {
44
+ '@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
45
+ },
36
46
  },
37
47
  rules: {
38
48
  ...sharedRules,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TypeScript File Configurations
3
3
  *
4
- * Handles all TypeScript (.ts) file-specific rules.
4
+ * Handles all TypeScript (.ts, .mts, .cts) file-specific rules.
5
5
  * Plugin registration removed - all plugins registered globally in index.js.
6
6
  */
7
7
 
@@ -15,7 +15,7 @@ export const typescriptConfig = (
15
15
  ) => [
16
16
  // TypeScript files - Base config
17
17
  {
18
- files: ['**/*.ts'],
18
+ files: ['**/*.ts', '**/*.mts', '**/*.cts'],
19
19
  ignores: [
20
20
  '**/node_modules/**',
21
21
  '**/dist/**',
@@ -30,14 +30,33 @@ export const typescriptConfig = (
30
30
  },
31
31
  },
32
32
  settings: {
33
+ react: {
34
+ version: 'detect',
35
+ },
33
36
  'import/resolver': {
34
37
  typescript: {},
35
38
  },
39
+ // Tell eslint-plugin-import to parse TypeScript dependency files with the
40
+ // TS parser. Without this, the resolver finds the file but the plugin
41
+ // cannot read its imports/exports, so cross-file rules like
42
+ // import/no-cycle silently never fire on .ts/.tsx code.
43
+ 'import/parsers': {
44
+ '@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
45
+ },
36
46
  },
37
47
  rules: {
38
48
  ...sharedRules,
39
49
  ...allRules.typescriptEslintRules,
40
50
  'no-undef': 'off', // TypeScript handles this
51
+ 'jsdoc/require-jsdoc': [
52
+ 'error',
53
+ {
54
+ require: {
55
+ ClassDeclaration: true,
56
+ FunctionDeclaration: true,
57
+ },
58
+ },
59
+ ],
41
60
  'custom/no-default-class-export': 'error',
42
61
  'single-export/single-export': 'error',
43
62
  'required-exports/required-exports': [
@@ -0,0 +1,10 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * DDD preset. The DDD rules (`require-spec-file`) now ship in the base config,
5
+ * so this entry point is equivalent to the default `eslint-config-agent`
6
+ * export and is kept for backward compatibility.
7
+ */
8
+ declare const config: Linter.Config[]
9
+
10
+ export default config
package/exports/ddd.js CHANGED
@@ -10,6 +10,4 @@
10
10
  * - import config from "eslint-config-agent/ddd" (same as above)
11
11
  */
12
12
 
13
- import config from '../index.js'
14
-
15
- export default config
13
+ export { default } from '../index.js'
@@ -0,0 +1,11 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * Incremental adoption preset: the full `eslint-config-agent` ruleset with every
5
+ * error-level rule downgraded to a warning. `eslint` exits `0` so CI stays
6
+ * green while the complete backlog is still reported, letting a team burn it
7
+ * down before flipping back to errors.
8
+ */
9
+ declare const config: Linter.Config[]
10
+
11
+ export default config
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Incremental adoption preset.
3
+ *
4
+ * Dropping the full strict ruleset onto an existing codebase surfaces a large
5
+ * backlog of pre-existing violations at once, so `eslint` exits non-zero and CI
6
+ * goes red on the very first run. Teams then either give up or copy-paste a
7
+ * helper that rewrites every `error` rule to `warn` — the exact same block,
8
+ * repeated in every repo that adopts this config.
9
+ *
10
+ * This entry point ships that pattern so it no longer has to be copy-pasted:
11
+ *
12
+ * ```js
13
+ * import incremental from 'eslint-config-agent/incremental'
14
+ *
15
+ * export default incremental
16
+ * ```
17
+ *
18
+ * `incremental` is the full `eslint-config-agent` ruleset with every
19
+ * error-level rule downgraded to a warning. `eslint` exits `0`, so `pnpm lint`
20
+ * (and CI) stays green, while the complete ruleset is still reported — letting a
21
+ * team burn the backlog down gradually and flip back to errors once it is clear.
22
+ *
23
+ * To enforce a rule as a hard error before the rest of the backlog is cleared,
24
+ * append your own override layer, which wins over the warned defaults:
25
+ *
26
+ * ```js
27
+ * import incremental from 'eslint-config-agent/incremental'
28
+ *
29
+ * export default [
30
+ * ...incremental,
31
+ * { rules: { eqeqeq: ['error', 'always'] } },
32
+ * ]
33
+ * ```
34
+ */
35
+
36
+ import config from '../index.js'
37
+ import { toWarnings } from './to-warnings.js'
38
+
39
+ export default config.map(toWarnings)
@@ -0,0 +1,11 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * Recommended + incremental preset: the `recommended` config with every
5
+ * surviving error-level rule downgraded to a warning. The gentlest on-ramp —
6
+ * the noisiest rules are off and everything else warns, so `eslint` exits `0`
7
+ * while the remaining backlog is still reported.
8
+ */
9
+ declare const config: Linter.Config[]
10
+
11
+ export default config
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Recommended + incremental (relaxed, warn-level) preset.
3
+ *
4
+ * The package already ships two adoption on-ramps, but each only solves half of
5
+ * what an existing codebase hits on the first lint run:
6
+ *
7
+ * - `recommended` turns the most divisive rules **off** (spec files, single
8
+ * export, custom `error/*`, optional chaining / nullish-coalescing bans,
9
+ * and so on) — but every remaining rule still reports as an **error**, so a
10
+ * real backlog still fails CI on the first run.
11
+ * - `incremental` keeps **every** rule reporting but downgrades them all to
12
+ * **warnings** — so CI stays green, yet the divisive rules keep firing as a
13
+ * wall of warnings on idiomatic TypeScript and React/Preact + Tailwind code.
14
+ *
15
+ * The gentlest possible on-ramp is the combination of the two: relax the
16
+ * divisive rules entirely *and* downgrade everything else to a warning. That is
17
+ * exactly this preset — the `recommended` config with every surviving
18
+ * error-level rule rewritten to `warn`:
19
+ *
20
+ * ```js
21
+ * import recommendedIncremental from 'eslint-config-agent/recommended-incremental'
22
+ *
23
+ * export default recommendedIncremental
24
+ * ```
25
+ *
26
+ * `eslint` exits `0`, so `pnpm lint` (and CI) stays green, the noisiest rules
27
+ * are silent, and the remaining quality rules show up as warnings you can burn
28
+ * down before tightening back up.
29
+ *
30
+ * To enforce a rule as a hard error before the rest of the backlog is cleared,
31
+ * append your own override layer, which wins over the warned defaults:
32
+ *
33
+ * ```js
34
+ * import recommendedIncremental from 'eslint-config-agent/recommended-incremental'
35
+ *
36
+ * export default [
37
+ * ...recommendedIncremental,
38
+ * { rules: { eqeqeq: ['error', 'always'] } },
39
+ * ]
40
+ * ```
41
+ */
42
+
43
+ import recommended from './recommended.js'
44
+ import { toWarnings } from './to-warnings.js'
45
+
46
+ export default recommended.map(toWarnings)
@@ -0,0 +1,11 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * Recommended (relaxed) preset: the default config with the most divisive rules
5
+ * turned off (spec files, single export, custom `error/*`, optional chaining /
6
+ * nullish-coalescing bans, and so on) for incremental adoption. Every surviving
7
+ * rule still reports as an error.
8
+ */
9
+ declare const config: Linter.Config[]
10
+
11
+ export default config
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Recommended (relaxed) preset.
3
+ *
4
+ * The default export is intentionally strict — it is tuned for greenfield
5
+ * projects that adopt every convention from day one (a spec file beside every
6
+ * source file, custom Error classes, no optional chaining / nullish
7
+ * coalescing, single export per module, and so on).
8
+ *
9
+ * Existing codebases usually cannot satisfy all of that at once, so they end
10
+ * up copying the same block of rule overrides into their own
11
+ * `eslint.config.js` just to get the config to load without a wall of errors.
12
+ *
13
+ * This preset bundles those common overrides so incremental adopters can opt
14
+ * into the core quality rules immediately while deferring the most opinionated
15
+ * ones:
16
+ *
17
+ * ```js
18
+ * import recommended from 'eslint-config-agent/recommended'
19
+ *
20
+ * export default recommended
21
+ * ```
22
+ *
23
+ * Re-enable any individual rule by appending your own override layer.
24
+ */
25
+
26
+ import config from '../index.js'
27
+
28
+ const relaxedOverrides = {
29
+ name: 'eslint-config-agent/recommended-overrides',
30
+ rules: {
31
+ // Don't require a `*.spec.*` file alongside every source file. The strict
32
+ // default splits this requirement across two rules: `ddd/require-spec-file`
33
+ // covers `.js`/`.ts` (the upstream `eslint-plugin-ddd` rule bails out on any
34
+ // other extension), and the bundled `custom/require-spec-file-tsx` covers
35
+ // `.tsx`/`.jsx` — i.e. the React/Preact components this config primarily
36
+ // targets. Relaxing only the first would still force a spec file beside
37
+ // every component, defeating the preset's purpose for its core audience, so
38
+ // both halves are disabled together here.
39
+ 'ddd/require-spec-file': 'off',
40
+ 'custom/require-spec-file-tsx': 'off',
41
+ // Allow multiple exports per module.
42
+ 'single-export/single-export': 'off',
43
+ 'required-exports/required-exports': 'off',
44
+ // Allow generic `Error` instead of mandating custom Error classes.
45
+ 'error/no-generic-error': 'off',
46
+ 'error/require-custom-error': 'off',
47
+ 'error/no-literal-error-message': 'off',
48
+ // Don't require a JSDoc block on every exported function and class. The
49
+ // strict default enables `jsdoc/require-jsdoc` at `error` for every
50
+ // `FunctionDeclaration` and `ClassDeclaration` (see `index.js` and
51
+ // `configs/typescript.js`), so adopting the config on an existing codebase
52
+ // produces a wall of `Missing JSDoc comment` errors on day one. This is the
53
+ // third of the three highest-volume on-ramp rules the README calls out —
54
+ // alongside `ddd/require-spec-file` and `error/no-literal-error-message`,
55
+ // both already relaxed above — so relax it here to match the preset's
56
+ // stated incremental-adoption purpose. Only the "document everything"
57
+ // requirement is lifted: the jsdoc *content* rules (`check-param-names`,
58
+ // `require-returns`, ...) stay enabled, so any JSDoc that is actually
59
+ // written is still validated.
60
+ 'jsdoc/require-jsdoc': 'off',
61
+ // Allow default parameter values.
62
+ 'default/no-default-params': 'off',
63
+ // Allow `type` aliases, not just `interface` declarations.
64
+ '@typescript-eslint/consistent-type-definitions': 'off',
65
+ // Don't require a semantic `className` on every HTML element, and don't
66
+ // reject Tailwind-only class lists. The strict default enables
67
+ // `jsx-classname/require-classname` with `{ ignoreTailwind: true }`, which
68
+ // errors both on elements with no `className` and on elements whose
69
+ // `className` contains only Tailwind utilities (e.g.
70
+ // `<div className="flex gap-2" />`). That makes the config impossible to
71
+ // adopt incrementally in any React/Preact + Tailwind codebase — by far the
72
+ // most common modern setup — so relax it for the recommended preset.
73
+ 'jsx-classname/require-classname': 'off',
74
+ // The most divisive layer: this is where optional chaining (`?.`),
75
+ // nullish coalescing (`??`), type assertions and switch-default bans live.
76
+ // Relaxing it lets idiomatic TypeScript through during adoption.
77
+ 'no-restricted-syntax': 'off',
78
+ },
79
+ }
80
+
81
+ export default [...config, relaxedOverrides]
@@ -0,0 +1,20 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * Downgrade every error-level rule in a flat-config block to a warning.
5
+ *
6
+ * The single source of truth used internally by the
7
+ * `eslint-config-agent/incremental` and
8
+ * `eslint-config-agent/recommended-incremental` presets. Map it over a
9
+ * flat-config array to warn-level the shared ruleset while composing your own
10
+ * config — for example to keep a handful of rules as hard errors from day one
11
+ * without copy-pasting the downgrade logic by hand.
12
+ *
13
+ * Blocks without a `rules` object (for example `ignores`-only blocks) are
14
+ * returned untouched. Both shorthand (`'error'`) and tuple (`['error',
15
+ * options]`) rule values are handled, and `off`/`warn` rules are left exactly
16
+ * as they are.
17
+ * @param block A flat-config block.
18
+ * @returns The block with error-level rules downgraded to warnings.
19
+ */
20
+ export declare const toWarnings: (block: Linter.Config) => Linter.Config
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared severity-downgrade helper for the warn-level adoption presets.
3
+ *
4
+ * Both `eslint-config-agent/incremental` and
5
+ * `eslint-config-agent/recommended-incremental` need to take a built flat-config
6
+ * array and rewrite every error-level rule to a warning so `eslint` exits `0`
7
+ * while still reporting the full backlog. That logic lived inline in
8
+ * `incremental.js`; extracting it here keeps a single source of truth so the two
9
+ * presets cannot drift apart.
10
+ */
11
+
12
+ const WARN = 'warn'
13
+ const ERROR_LEVELS = new Set(['error', 2])
14
+
15
+ const downgrade = severity => (ERROR_LEVELS.has(severity) ? WARN : severity)
16
+
17
+ /**
18
+ * Downgrade every error-level rule in a flat-config block to a warning.
19
+ *
20
+ * Blocks without a `rules` object (for example `ignores`-only blocks) are
21
+ * returned untouched. Both shorthand (`'error'`) and tuple
22
+ * (`['error', options]`) rule values are handled, and `off`/`warn` rules are
23
+ * left exactly as they are.
24
+ * @param block A flat-config block.
25
+ * @returns The block with error-level rules downgraded to warnings.
26
+ */
27
+ export const toWarnings = block => {
28
+ if (block.rules === undefined) {
29
+ return block
30
+ }
31
+
32
+ const rules = Object.fromEntries(
33
+ Object.entries(block.rules).map(([name, value]) =>
34
+ Array.isArray(value)
35
+ ? [name, [downgrade(value[0]), ...value.slice(1)]]
36
+ : [name, downgrade(value)]
37
+ )
38
+ )
39
+
40
+ return { ...block, rules }
41
+ }
package/index.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ /**
4
+ * The default `eslint-config-agent` flat config: the full strict ruleset for
5
+ * TypeScript, React, and Preact projects.
6
+ *
7
+ * It is an array of flat-config blocks, so spread it into (or export it
8
+ * directly as) your `eslint.config.*`:
9
+ *
10
+ * ```ts
11
+ * import config from 'eslint-config-agent'
12
+ *
13
+ * export default config
14
+ * ```
15
+ */
16
+ declare const config: Linter.Config[]
17
+
18
+ export default config