@testgorilla/tgo-linting 3.0.0 → 5.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.
- package/Readme.md +47 -64
- package/package.json +6 -6
- package/src/configs/recommended.d.ts +12 -2
- package/src/configs/recommended.js +176 -59
- package/src/configs/recommended.js.map +1 -1
package/Readme.md
CHANGED
|
@@ -8,11 +8,34 @@ Linting rules and code quality standards for TestGorilla projects.
|
|
|
8
8
|
npm install @testgorilla/tgo-linting @angular-eslint/template-parser --save-dev
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Compatibility
|
|
12
|
+
|
|
13
|
+
| tgo-linting | ESLint | angular-eslint | Angular |
|
|
14
|
+
| ----------- | --------------------- | -------------- | ------------------------------------------------ |
|
|
15
|
+
| 5.x | `^9.0.0 \|\| ^10.0.0` | 21.x | any (angular-eslint 21 bundles its own compiler) |
|
|
16
|
+
| 4.x | `^8.57.0 \|\| ^9.0.0` | 20.x | any |
|
|
17
|
+
|
|
18
|
+
> **ESLint 9 consumers:** the bundled `eslint-plugin-rxjs-x@1.0.2` declares an
|
|
19
|
+
> `eslint: ^10` peer dependency (no release of that plugin supports ESLint 9 and 10
|
|
20
|
+
> simultaneously). Until your repo moves to ESLint 10, keep this override in your
|
|
21
|
+
> `package.json` so `npm install` resolves cleanly:
|
|
22
|
+
>
|
|
23
|
+
> ```json
|
|
24
|
+
> "overrides": {
|
|
25
|
+
> "eslint-plugin-rxjs-x": {
|
|
26
|
+
> "eslint": "$eslint"
|
|
27
|
+
> }
|
|
28
|
+
> }
|
|
29
|
+
> ```
|
|
30
|
+
>
|
|
31
|
+
> Consumers on ESLint 10 do not need the override.
|
|
32
|
+
|
|
11
33
|
## Usage
|
|
12
34
|
|
|
13
|
-
This package
|
|
35
|
+
This package requires ESLint flat config (`eslint.config.js`/`.mjs`) and ESLint 9 or 10.
|
|
36
|
+
Support for legacy `.eslintrc.*` configs and ESLint 8 was removed in 5.0.0.
|
|
14
37
|
|
|
15
|
-
### Flat Config
|
|
38
|
+
### Flat Config
|
|
16
39
|
|
|
17
40
|
**Recommended approach:**
|
|
18
41
|
|
|
@@ -44,51 +67,6 @@ export default [
|
|
|
44
67
|
];
|
|
45
68
|
```
|
|
46
69
|
|
|
47
|
-
### Legacy Config (ESLint 8.x and below)
|
|
48
|
-
|
|
49
|
-
**Using the legacy preset:**
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
// .eslintrc.js
|
|
53
|
-
const { legacy } = require('@testgorilla/tgo-linting');
|
|
54
|
-
|
|
55
|
-
module.exports = {
|
|
56
|
-
// Your base config
|
|
57
|
-
extends: [
|
|
58
|
-
// Your other extends
|
|
59
|
-
],
|
|
60
|
-
plugins: ['tgo'],
|
|
61
|
-
overrides: [
|
|
62
|
-
{
|
|
63
|
-
files: ['*.html'],
|
|
64
|
-
parser: '@angular-eslint/template-parser',
|
|
65
|
-
...legacy,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
};
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**Manual configuration:**
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
// .eslintrc.js
|
|
75
|
-
module.exports = {
|
|
76
|
-
plugins: ['tgo'],
|
|
77
|
-
extends: [
|
|
78
|
-
// Your other extends
|
|
79
|
-
],
|
|
80
|
-
overrides: [
|
|
81
|
-
{
|
|
82
|
-
files: ['*.html'],
|
|
83
|
-
parser: '@angular-eslint/template-parser',
|
|
84
|
-
rules: {
|
|
85
|
-
'tgo/require-data-testid': 'warn', // Example rule configuration
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
};
|
|
90
|
-
```
|
|
91
|
-
|
|
92
70
|
## Important Notes
|
|
93
71
|
|
|
94
72
|
- **Template Parser Required:** The `tgo/require-data-testid` rule only works with HTML/Angular templates. You must configure `@angular-eslint/template-parser` for `.html` files.
|
|
@@ -98,8 +76,8 @@ module.exports = {
|
|
|
98
76
|
|
|
99
77
|
### Available Rules
|
|
100
78
|
|
|
101
|
-
| Rule
|
|
102
|
-
|
|
79
|
+
| Rule | Description |
|
|
80
|
+
| ------------------------- | ----------------------------------------------------------------------------- |
|
|
103
81
|
| `tgo/require-data-testid` | Ensures specific HTML elements have a `data-testid` attribute for E2E testing |
|
|
104
82
|
|
|
105
83
|
### Rule Documentation
|
|
@@ -113,10 +91,11 @@ Detailed documentation for each rule, including examples and configuration optio
|
|
|
113
91
|
To add a new ESLint rule to this package:
|
|
114
92
|
|
|
115
93
|
1. **Create the rule file** in `src/rules/`:
|
|
94
|
+
|
|
116
95
|
```typescript
|
|
117
96
|
// src/rules/your-rule-name.ts
|
|
118
|
-
import { Rule } from 'eslint'
|
|
119
|
-
|
|
97
|
+
import { Rule } from 'eslint';
|
|
98
|
+
|
|
120
99
|
const rule: Rule.RuleModule = {
|
|
121
100
|
meta: {
|
|
122
101
|
type: 'problem', // or 'suggestion' or 'layout'
|
|
@@ -134,22 +113,23 @@ To add a new ESLint rule to this package:
|
|
|
134
113
|
// Your rule implementation
|
|
135
114
|
return {
|
|
136
115
|
// AST node visitors
|
|
137
|
-
}
|
|
116
|
+
};
|
|
138
117
|
},
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export default rule
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default rule;
|
|
142
121
|
```
|
|
143
122
|
|
|
144
123
|
2. **Add tests** in `src/rules/your-rule-name.spec.ts`:
|
|
124
|
+
|
|
145
125
|
```typescript
|
|
146
|
-
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
147
|
-
import rule from './your-rule-name'
|
|
148
|
-
|
|
126
|
+
import { RuleTester } from '@typescript-eslint/rule-tester';
|
|
127
|
+
import rule from './your-rule-name';
|
|
128
|
+
|
|
149
129
|
const ruleTester = new RuleTester({
|
|
150
130
|
parser: '@angular-eslint/template-parser',
|
|
151
|
-
})
|
|
152
|
-
|
|
131
|
+
});
|
|
132
|
+
|
|
153
133
|
ruleTester.run('your-rule-name', rule, {
|
|
154
134
|
valid: [
|
|
155
135
|
// Test cases that should pass
|
|
@@ -157,20 +137,22 @@ To add a new ESLint rule to this package:
|
|
|
157
137
|
invalid: [
|
|
158
138
|
// Test cases that should fail
|
|
159
139
|
],
|
|
160
|
-
})
|
|
140
|
+
});
|
|
161
141
|
```
|
|
162
142
|
|
|
163
143
|
3. **Export the rule** in `src/rules/index.ts`:
|
|
144
|
+
|
|
164
145
|
```typescript
|
|
165
|
-
import yourRuleName from './your-rule-name'
|
|
166
|
-
|
|
146
|
+
import yourRuleName from './your-rule-name';
|
|
147
|
+
|
|
167
148
|
export const rules = {
|
|
168
149
|
'require-data-testid': requireDataTestId,
|
|
169
150
|
'your-rule-name': yourRuleName,
|
|
170
|
-
}
|
|
151
|
+
};
|
|
171
152
|
```
|
|
172
153
|
|
|
173
154
|
4. **Add to recommended config** (optional) in `src/configs/recommended.ts`:
|
|
155
|
+
|
|
174
156
|
```typescript
|
|
175
157
|
rules: {
|
|
176
158
|
'tgo/require-data-testid': 'warn',
|
|
@@ -179,6 +161,7 @@ To add a new ESLint rule to this package:
|
|
|
179
161
|
```
|
|
180
162
|
|
|
181
163
|
5. **Document the rule** in `src/rules/your-rule-name.md`:
|
|
164
|
+
|
|
182
165
|
- Describe what the rule does
|
|
183
166
|
- Provide configuration options
|
|
184
167
|
- Show correct and incorrect code examples
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testgorilla/tgo-linting",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"displayName": "TGO Linting",
|
|
5
5
|
"description": "Linting rules and code quality standards for TestGorilla projects",
|
|
6
6
|
"author": "TestGorilla",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"registry": "https://registry.npmjs.org/"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@angular-eslint/eslint-plugin": "^
|
|
28
|
-
"@angular-eslint/eslint-plugin-template": "^
|
|
29
|
-
"@angular-eslint/template-parser": "^
|
|
27
|
+
"@angular-eslint/eslint-plugin": "^21.4.0",
|
|
28
|
+
"@angular-eslint/eslint-plugin-template": "^21.4.0",
|
|
29
|
+
"@angular-eslint/template-parser": "^21.4.0",
|
|
30
30
|
"@typescript-eslint/utils": "^8.56.1",
|
|
31
31
|
"eslint-config-prettier": "10.1.8",
|
|
32
32
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
33
|
-
"eslint-plugin-import-x": "4.16.
|
|
33
|
+
"eslint-plugin-import-x": "4.16.2",
|
|
34
34
|
"eslint-plugin-jsdoc": "62.7.1",
|
|
35
35
|
"eslint-plugin-no-unsanitized": "4.1.5",
|
|
36
36
|
"eslint-plugin-rxjs-x": "1.0.2",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typescript-eslint": "8.56.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"eslint": "^
|
|
41
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
42
42
|
"typescript": ">=4.8.4 <6.0.0",
|
|
43
43
|
"tslib": "^2.0.0"
|
|
44
44
|
},
|
|
@@ -15,7 +15,17 @@ export interface RecommendedOptions {
|
|
|
15
15
|
* Strict default ESLint flat-config preset for TGO Angular frontends.
|
|
16
16
|
*
|
|
17
17
|
* Type-aware rules (no-unsafe-*, restrict-*, no-floating-promises, etc.) are
|
|
18
|
-
*
|
|
19
|
-
* after the strict tsconfig migration
|
|
18
|
+
* at `error`. The previously-deferred warn severities were ratcheted to error
|
|
19
|
+
* after the strict tsconfig migration landed in consumer codebases. Two rules
|
|
20
|
+
* remain explicitly relaxed in the preset:
|
|
21
|
+
* - `@typescript-eslint/consistent-type-imports` (off — Angular DI conflict)
|
|
22
|
+
* - `@angular-eslint/use-component-view-encapsulation` (off — separate
|
|
23
|
+
* styling refactor workstream)
|
|
24
|
+
* See the inline comments at each rule for full rationale.
|
|
25
|
+
*
|
|
26
|
+
* The spec/mock files block (default glob: *.spec.ts + *.integration.spec.ts
|
|
27
|
+
* + *.mock.ts + *.mocks.ts) relaxes type-aware family rules and a few others
|
|
28
|
+
* to match the idiomatic test-code shape (bracket access, fire-trigger
|
|
29
|
+
* subscribes, mock literals with `any` typing).
|
|
20
30
|
*/
|
|
21
31
|
export declare function recommended(opts: RecommendedOptions): ConfigArray;
|
|
@@ -24,11 +24,26 @@ const tseslintRecommendedTypeChecked = typescript_eslint_1.default.configs.recom
|
|
|
24
24
|
* Strict default ESLint flat-config preset for TGO Angular frontends.
|
|
25
25
|
*
|
|
26
26
|
* Type-aware rules (no-unsafe-*, restrict-*, no-floating-promises, etc.) are
|
|
27
|
-
*
|
|
28
|
-
* after the strict tsconfig migration
|
|
27
|
+
* at `error`. The previously-deferred warn severities were ratcheted to error
|
|
28
|
+
* after the strict tsconfig migration landed in consumer codebases. Two rules
|
|
29
|
+
* remain explicitly relaxed in the preset:
|
|
30
|
+
* - `@typescript-eslint/consistent-type-imports` (off — Angular DI conflict)
|
|
31
|
+
* - `@angular-eslint/use-component-view-encapsulation` (off — separate
|
|
32
|
+
* styling refactor workstream)
|
|
33
|
+
* See the inline comments at each rule for full rationale.
|
|
34
|
+
*
|
|
35
|
+
* The spec/mock files block (default glob: *.spec.ts + *.integration.spec.ts
|
|
36
|
+
* + *.mock.ts + *.mocks.ts) relaxes type-aware family rules and a few others
|
|
37
|
+
* to match the idiomatic test-code shape (bracket access, fire-trigger
|
|
38
|
+
* subscribes, mock literals with `any` typing).
|
|
29
39
|
*/
|
|
30
40
|
function recommended(opts) {
|
|
31
|
-
const { tsconfigRootDir, project = 'tsconfig.json', tsFiles = ['src/**/*.ts'], htmlFiles = ['src/**/*.html'], specFiles = [
|
|
41
|
+
const { tsconfigRootDir, project = 'tsconfig.json', tsFiles = ['src/**/*.ts'], htmlFiles = ['src/**/*.html'], specFiles = [
|
|
42
|
+
'src/**/*.spec.ts',
|
|
43
|
+
'src/**/*.integration.spec.ts',
|
|
44
|
+
'src/**/*.mock.ts',
|
|
45
|
+
'src/**/*.mocks.ts',
|
|
46
|
+
], } = opts;
|
|
32
47
|
return typescript_eslint_1.default.config(
|
|
33
48
|
// ── TypeScript files (*.ts) ──────────────────────────────────────────
|
|
34
49
|
{
|
|
@@ -64,45 +79,59 @@ function recommended(opts) {
|
|
|
64
79
|
...tseslintRecommendedTypeChecked,
|
|
65
80
|
...eslint_config_prettier_1.default.rules,
|
|
66
81
|
// ══════════════════════════════════════════════════════════════════
|
|
67
|
-
// Type-aware rules —
|
|
68
|
-
//
|
|
82
|
+
// Type-aware rules — ERROR (ratcheted from warn after TS strict landed
|
|
83
|
+
// in consumer codebases).
|
|
69
84
|
// ══════════════════════════════════════════════════════════════════
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'@typescript-eslint/no-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
'@typescript-eslint/no-
|
|
86
|
-
'@typescript-eslint/
|
|
87
|
-
'@typescript-eslint/
|
|
88
|
-
'@typescript-eslint/no-
|
|
89
|
-
'@typescript-eslint/no-
|
|
90
|
-
'@typescript-eslint/no-
|
|
91
|
-
'@typescript-eslint/no-
|
|
92
|
-
'@typescript-eslint/
|
|
93
|
-
'@typescript-eslint/
|
|
94
|
-
'@typescript-eslint/
|
|
95
|
-
'@typescript-eslint/
|
|
96
|
-
'@typescript-eslint/prefer-
|
|
97
|
-
'@typescript-eslint/
|
|
98
|
-
'@typescript-eslint/
|
|
99
|
-
'@typescript-eslint/
|
|
100
|
-
'@typescript-eslint/
|
|
101
|
-
'@typescript-eslint/
|
|
102
|
-
'@typescript-eslint/no-
|
|
85
|
+
// `_`-prefix is the conventional opt-out for intentionally-unused
|
|
86
|
+
// identifiers in TypeScript (matches the `noUnusedParameters` compiler
|
|
87
|
+
// option's behavior). Mock/stub methods that need a signature-compatible
|
|
88
|
+
// parameter but ignore the value (e.g. `configure(_config?: …) {}`),
|
|
89
|
+
// destructured rest collectors (`const { _internal: _, ...rest } = obj`),
|
|
90
|
+
// and `catch (_e: unknown)` blocks all benefit. Production code can't
|
|
91
|
+
// accidentally hide real unused names — pick a different prefix.
|
|
92
|
+
'@typescript-eslint/no-unused-vars': [
|
|
93
|
+
'error',
|
|
94
|
+
{
|
|
95
|
+
argsIgnorePattern: '^_',
|
|
96
|
+
varsIgnorePattern: '^_',
|
|
97
|
+
caughtErrorsIgnorePattern: '^_',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
'@typescript-eslint/no-unsafe-assignment': 'error',
|
|
101
|
+
'@typescript-eslint/no-unsafe-call': 'error',
|
|
102
|
+
'@typescript-eslint/no-unsafe-member-access': 'error',
|
|
103
|
+
'@typescript-eslint/no-unsafe-return': 'error',
|
|
104
|
+
'@typescript-eslint/no-unsafe-argument': 'error',
|
|
105
|
+
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
|
|
106
|
+
'@typescript-eslint/no-unsafe-unary-minus': 'error',
|
|
107
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
108
|
+
'@typescript-eslint/no-misused-promises': 'error',
|
|
109
|
+
'@typescript-eslint/await-thenable': 'error',
|
|
110
|
+
'@typescript-eslint/only-throw-error': 'error',
|
|
111
|
+
'@typescript-eslint/prefer-promise-reject-errors': 'error',
|
|
112
|
+
'@typescript-eslint/require-await': 'error',
|
|
113
|
+
'@typescript-eslint/return-await': ['error', 'in-try-catch'],
|
|
114
|
+
'@typescript-eslint/no-base-to-string': 'error',
|
|
115
|
+
'@typescript-eslint/restrict-template-expressions': 'error',
|
|
116
|
+
'@typescript-eslint/restrict-plus-operands': 'error',
|
|
117
|
+
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
|
|
118
|
+
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
|
119
|
+
'@typescript-eslint/no-deprecated': 'error',
|
|
120
|
+
'@typescript-eslint/no-meaningless-void-operator': 'error',
|
|
121
|
+
'@typescript-eslint/prefer-readonly': 'error',
|
|
122
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
|
123
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
124
|
+
'@typescript-eslint/prefer-includes': 'error',
|
|
125
|
+
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
|
126
|
+
'@typescript-eslint/prefer-literal-enum-member': 'error',
|
|
127
|
+
'@typescript-eslint/no-mixed-enums': 'error',
|
|
128
|
+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
129
|
+
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
|
|
130
|
+
'@typescript-eslint/unbound-method': 'error',
|
|
131
|
+
'@typescript-eslint/no-wrapper-object-types': 'error',
|
|
103
132
|
'@typescript-eslint/no-unsafe-function-type': 'off',
|
|
104
133
|
'dot-notation': 'off',
|
|
105
|
-
'@typescript-eslint/dot-notation': ['
|
|
134
|
+
'@typescript-eslint/dot-notation': ['error', { allowIndexSignaturePropertyAccess: true }],
|
|
106
135
|
// ══════════════════════════════════════════════════════════════════
|
|
107
136
|
// Type-aware rules at error — purely syntactic, safe without TS strict.
|
|
108
137
|
// ══════════════════════════════════════════════════════════════════
|
|
@@ -148,9 +177,15 @@ function recommended(opts) {
|
|
|
148
177
|
'@typescript-eslint/array-type': 'off',
|
|
149
178
|
'@typescript-eslint/parameter-properties': 'off',
|
|
150
179
|
'@typescript-eslint/explicit-member-accessibility': ['off', { accessibility: 'explicit' }],
|
|
151
|
-
// Naming convention — Angular-friendly, lenient.
|
|
180
|
+
// Naming convention — Angular-friendly, lenient. Error severity (ratcheted
|
|
181
|
+
// from warn). Selectors below opt out of naming enforcement for the
|
|
182
|
+
// identifier kinds that legitimately mirror the snake_case shape of
|
|
183
|
+
// TestGorilla's backend API (DTOs, destructured server responses,
|
|
184
|
+
// class fields that proxy API field names, Quill keyboard-shortcut /
|
|
185
|
+
// language object-literal method keys like `Cmd-Z` or `c++`).
|
|
186
|
+
// Last-matching-selector-wins, so the additions go at the tail.
|
|
152
187
|
'@typescript-eslint/naming-convention': [
|
|
153
|
-
'
|
|
188
|
+
'error',
|
|
154
189
|
{
|
|
155
190
|
selector: 'default',
|
|
156
191
|
format: ['camelCase'],
|
|
@@ -174,6 +209,16 @@ function recommended(opts) {
|
|
|
174
209
|
// API payloads commonly use snake_case — opt out of property naming entirely.
|
|
175
210
|
{ selector: 'objectLiteralProperty', format: null },
|
|
176
211
|
{ selector: 'import', format: null },
|
|
212
|
+
// Interface / type members modelling API shape.
|
|
213
|
+
{ selector: 'typeProperty', format: null },
|
|
214
|
+
// DTO classes + UPPER_CASE static const-like fields + PascalCase class-field
|
|
215
|
+
// re-exports of types/enums to templates.
|
|
216
|
+
{ selector: 'classProperty', format: null, leadingUnderscore: 'allow' },
|
|
217
|
+
// `const { foo_bar } = result;` destructured locals/parameters keep API names.
|
|
218
|
+
{ selector: 'variable', modifiers: ['destructured'], format: null },
|
|
219
|
+
{ selector: 'parameter', modifiers: ['destructured'], format: null },
|
|
220
|
+
// Quill keyboard shortcuts (`Cmd-Z`, `Ctrl-Shift-K`) and language keys (`c++`, `c#`).
|
|
221
|
+
{ selector: 'objectLiteralMethod', format: null },
|
|
177
222
|
],
|
|
178
223
|
'@typescript-eslint/no-restricted-types': [
|
|
179
224
|
'error',
|
|
@@ -231,7 +276,15 @@ function recommended(opts) {
|
|
|
231
276
|
'@angular-eslint/use-pipe-transform-interface': 'error',
|
|
232
277
|
'@angular-eslint/prefer-standalone': 'error',
|
|
233
278
|
'@angular-eslint/prefer-on-push-component-change-detection': 'error',
|
|
234
|
-
|
|
279
|
+
// use-component-view-encapsulation — off in the preset. Re-enabling
|
|
280
|
+
// requires per-component audit of every `ViewEncapsulation.None` site
|
|
281
|
+
// (third-party DOM targets, global content-projection slots, intentional
|
|
282
|
+
// style leaks) and a refactor for the accidental ones. That work belongs
|
|
283
|
+
// in a dedicated styling-focused workstream in each consumer codebase,
|
|
284
|
+
// not in this preset's strict default. Consumers can override to
|
|
285
|
+
// `error` locally if they want to gate on it sooner. TODO: revisit
|
|
286
|
+
// when at least one consumer ships the per-component audit.
|
|
287
|
+
'@angular-eslint/use-component-view-encapsulation': 'off',
|
|
235
288
|
'@angular-eslint/no-queries-metadata-property': 'error',
|
|
236
289
|
'@angular-eslint/no-duplicates-in-metadata-arrays': 'error',
|
|
237
290
|
'@angular-eslint/no-async-lifecycle-method': 'error',
|
|
@@ -247,11 +300,10 @@ function recommended(opts) {
|
|
|
247
300
|
'import-x/no-self-import': 'error',
|
|
248
301
|
'import-x/no-duplicates': 'error',
|
|
249
302
|
// PERF NOTE — TIMING profile shows this rule at 64-75% of total rule execution time
|
|
250
|
-
// (~1.1-1.3s per file). It walks every import looking for @deprecated JSDoc tags
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
'import-x/no-deprecated': 'warn',
|
|
303
|
+
// (~1.1-1.3s per file). It walks every import looking for @deprecated JSDoc tags. Ratcheted
|
|
304
|
+
// to error along with the rest of the type-aware family after TS strict landed. Revisit
|
|
305
|
+
// migrating to OXLint's fast path with Workstream 1 if total lint time becomes a concern.
|
|
306
|
+
'import-x/no-deprecated': 'error',
|
|
255
307
|
'import-x/no-relative-packages': 'error',
|
|
256
308
|
'import-x/no-mutable-exports': 'error',
|
|
257
309
|
'import-x/no-extraneous-dependencies': 'error',
|
|
@@ -294,19 +346,21 @@ function recommended(opts) {
|
|
|
294
346
|
'security/detect-no-csrf-before-method-override': 'off',
|
|
295
347
|
'security/detect-possible-timing-attacks': 'off',
|
|
296
348
|
// ══════════════════════════════════════════════════════════════════
|
|
297
|
-
// RxJS hygiene (eslint-plugin-rxjs-x).
|
|
298
|
-
//
|
|
349
|
+
// RxJS hygiene (eslint-plugin-rxjs-x). Error severity (ratcheted from
|
|
350
|
+
// warn after TS strict landed). All five are real-bug-class rules
|
|
351
|
+
// (async-in-subscribe, untyped catch in pipe, nested subscribes that
|
|
352
|
+
// should be flatMap, completer-not-last, leaking subscriptions).
|
|
299
353
|
// ══════════════════════════════════════════════════════════════════
|
|
300
|
-
'rxjs-x/no-async-subscribe': '
|
|
301
|
-
'rxjs-x/no-implicit-any-catch': '
|
|
302
|
-
'rxjs-x/no-nested-subscribe': '
|
|
303
|
-
'rxjs-x/no-unsafe-takeuntil': '
|
|
304
|
-
'rxjs-x/no-ignored-subscription': '
|
|
354
|
+
'rxjs-x/no-async-subscribe': 'error',
|
|
355
|
+
'rxjs-x/no-implicit-any-catch': 'error',
|
|
356
|
+
'rxjs-x/no-nested-subscribe': 'error',
|
|
357
|
+
'rxjs-x/no-unsafe-takeuntil': 'error',
|
|
358
|
+
'rxjs-x/no-ignored-subscription': 'error',
|
|
305
359
|
// ══════════════════════════════════════════════════════════════════
|
|
306
360
|
// Core ESLint — error.
|
|
307
361
|
// ══════════════════════════════════════════════════════════════════
|
|
308
362
|
'arrow-body-style': 'error',
|
|
309
|
-
complexity: ['
|
|
363
|
+
complexity: ['error', 15],
|
|
310
364
|
'constructor-super': 'error',
|
|
311
365
|
curly: 'error',
|
|
312
366
|
'default-case-last': 'error',
|
|
@@ -325,9 +379,9 @@ function recommended(opts) {
|
|
|
325
379
|
'undefined',
|
|
326
380
|
],
|
|
327
381
|
'max-classes-per-file': 'off',
|
|
328
|
-
'max-depth': ['
|
|
329
|
-
'max-nested-callbacks': ['
|
|
330
|
-
'max-params': ['
|
|
382
|
+
'max-depth': ['error', 4],
|
|
383
|
+
'max-nested-callbacks': ['error', 3],
|
|
384
|
+
'max-params': ['error', 5],
|
|
331
385
|
'no-bitwise': 'error',
|
|
332
386
|
'no-caller': 'error',
|
|
333
387
|
'no-cond-assign': 'error',
|
|
@@ -445,7 +499,13 @@ function recommended(opts) {
|
|
|
445
499
|
'@angular-eslint/template/prefer-control-flow': 'error',
|
|
446
500
|
},
|
|
447
501
|
},
|
|
448
|
-
// ── Spec files (*.spec.ts, *.integration.spec.ts
|
|
502
|
+
// ── Spec / mock files (default glob: *.spec.ts, *.integration.spec.ts,
|
|
503
|
+
// *.mock.ts, *.mocks.ts) — relax type-aware and a few style rules to
|
|
504
|
+
// match the idiomatic test-code shape (bracket access for production
|
|
505
|
+
// internals, fire-trigger subscribes that Jest cleans up via test
|
|
506
|
+
// isolation, mock literals with `any`-shaped fixtures, snake_case API
|
|
507
|
+
// field names re-used in fixture object literals). Also allows `ui-*`
|
|
508
|
+
// selectors for mocks that substitute Canopy UI library components. ──
|
|
449
509
|
{
|
|
450
510
|
files: specFiles,
|
|
451
511
|
rules: {
|
|
@@ -459,6 +519,63 @@ function recommended(opts) {
|
|
|
459
519
|
'@typescript-eslint/naming-convention': 'off',
|
|
460
520
|
'max-params': 'off',
|
|
461
521
|
'max-nested-callbacks': 'off',
|
|
522
|
+
// dot-notation: rule's autofix converts `service['privateField']` →
|
|
523
|
+
// `service.privateField`, which trips TS access-modifier checks
|
|
524
|
+
// (TS2341/TS2445) and/or no-underscore-dangle on `_`-prefixed
|
|
525
|
+
// internals. Bracket access is the standard idiom for reaching
|
|
526
|
+
// production internals from tests; the noise is purely cosmetic.
|
|
527
|
+
'@typescript-eslint/dot-notation': 'off',
|
|
528
|
+
// no-ignored-subscription: the canonical pattern in specs is
|
|
529
|
+
// `service.method().subscribe()` used as a fire-trigger for the
|
|
530
|
+
// production code's side effect (typically an HTTP request the spec
|
|
531
|
+
// then asserts via `httpTesting.expectOne`). Jest test isolation
|
|
532
|
+
// makes leaks impossible by construction, so the rule's
|
|
533
|
+
// memory-leak-prevention signal is zero here while the noise is
|
|
534
|
+
// substantial.
|
|
535
|
+
'rxjs-x/no-ignored-subscription': 'off',
|
|
536
|
+
// component-selector: mocks that substitute Canopy UI library
|
|
537
|
+
// components (`ui-*` selectors owned by `@testgorilla/tgo-ui`)
|
|
538
|
+
// must use the same selectors to slot in correctly under
|
|
539
|
+
// TestBed.overrideComponent.
|
|
540
|
+
'@angular-eslint/component-selector': [
|
|
541
|
+
'error',
|
|
542
|
+
{ type: 'element', prefix: ['tgo', 'ui'], style: 'kebab-case' },
|
|
543
|
+
],
|
|
544
|
+
// no-non-null-assertion: idiomatic `querySelector('input')!` after
|
|
545
|
+
// an `expect(...).toBeDefined()` or after a static template
|
|
546
|
+
// guarantees the element exists. The spec has already proven
|
|
547
|
+
// non-null upstream; the rule's signal is zero here while the
|
|
548
|
+
// noise is substantial. Same precedent as `dot-notation` /
|
|
549
|
+
// `no-ignored-subscription` — spec-file relaxations match the
|
|
550
|
+
// idiomatic test shape. Production code keeps the rule at error.
|
|
551
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
552
|
+
// no-underscore-dangle: specs routinely reach into `_`-prefixed
|
|
553
|
+
// internals of services and SignalStore factories to assert
|
|
554
|
+
// against private state (e.g. `(store as unknown as
|
|
555
|
+
// { _resetSubject: ... })._resetSubject()`). The SignalStore
|
|
556
|
+
// factory block already disables this rule for `*.store.ts` /
|
|
557
|
+
// `*.store.feature.ts`, but `*.store.spec.ts` matches the spec
|
|
558
|
+
// block instead — so the disable needs to be here too.
|
|
559
|
+
'no-underscore-dangle': 'off',
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
// ── NgRx SignalStore factory files (*.store.ts, *.store.feature.ts) —
|
|
563
|
+
// three rules conflict with the SignalStore authoring pattern:
|
|
564
|
+
// - `explicit-function-return-type`: signalStore() / withFeature()
|
|
565
|
+
// rely on inferred generic return types; naming the type either
|
|
566
|
+
// duplicates inference or narrows below what's intended.
|
|
567
|
+
// - `no-underscore-dangle`: SignalStore convention uses `_`-prefixed
|
|
568
|
+
// internal helpers (e.g. `_state`, `_load`) that don't leak through
|
|
569
|
+
// the public store API.
|
|
570
|
+
// - `prefer-arrow-callback`: factories pass `function` keyword
|
|
571
|
+
// callbacks for proper `this`-binding inside the feature; arrow
|
|
572
|
+
// conversion can change semantics. ──
|
|
573
|
+
{
|
|
574
|
+
files: ['src/**/*.store.ts', 'src/**/*.store.feature.ts'],
|
|
575
|
+
rules: {
|
|
576
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
577
|
+
'no-underscore-dangle': 'off',
|
|
578
|
+
'prefer-arrow-callback': 'off',
|
|
462
579
|
},
|
|
463
580
|
},
|
|
464
581
|
// ── JS files ─────────────────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../../../../packages/tgo-linting/src/configs/recommended.ts"],"names":[],"mappings":";;AAqDA,kCAwdC;;AA7gBD,0FAAoD;AACpD,4GAAqE;AACrE,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,kFAAkF;AAClF,gFAAgF;AAChF,+FAAyE;AACzE,4FAAoD;AACpD,4FAA6C;AAC7C,sFAAwC;AACxC,wGAAyD;AACzD,wFAAyC;AACzC,4FAA8C;AAC9C,kFAA+D;AAE/D,sCAAsC;AAQtC,MAAM,mBAAmB,GAAG,2BAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAC7D,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,WAAC,OAAA,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,MAAA,GAAG,CAAC,KAAK,mCAAI,EAAE,CAAC,EAAE,CAAC,CAAA,EAAA,EAChD,EAAE,CACH,CAAC;AACF,MAAM,8BAA8B,GAAG,2BAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CACnF,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,WAAC,OAAA,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,MAAA,GAAG,CAAC,KAAK,mCAAI,EAAE,CAAC,EAAE,CAAC,CAAA,EAAA,EAChD,EAAE,CACH,CAAC;AAeF;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,IAAwB;IAClD,MAAM,EACJ,eAAe,EACf,OAAO,GAAG,eAAe,EACzB,OAAO,GAAG,CAAC,aAAa,CAAC,EACzB,SAAS,GAAG,CAAC,eAAe,CAAC,EAC7B,SAAS,GAAG,CAAC,kBAAkB,EAAE,8BAA8B,CAAC,GACjE,GAAG,IAAI,CAAC;IAET,OAAO,2BAAQ,CAAC,MAAM;IACpB,wEAAwE;IACxE;QACE,KAAK,EAAE,OAAO;QACd,eAAe,EAAE;YACf,MAAM,EAAE,2BAAQ,CAAC,MAAM;YACvB,aAAa,EAAE;gBACb,OAAO;gBACP,eAAe;gBACf,UAAU,EAAE,QAAQ;aACrB;SACF;QACD,QAAQ,EAAE;YACR,mBAAmB,EAAE;gBACnB,UAAU,EAAE,EAAE,OAAO,EAAE;gBACvB,IAAI,EAAE,IAAI;aACX;SACF;QACD,OAAO,EAAE;YACP,oBAAoB,EAAE,2BAAQ,CAAC,MAAM;YACrC,iBAAiB,EAAE,uBAAO;YAC1B,UAAU,EAAE,gCAAO;YACnB,KAAK,EAAL,6BAAK;YACL,gBAAgB,EAAE,sCAAa;YAC/B,QAAQ,EAAR,gCAAQ;YACR,QAAQ,EAAE,8BAAK;SAChB;QACD,KAAK,EAAE;YACL,8EAA8E;YAC9E,0EAA0E;YAC1E,oEAAoE;YACpE,GAAG,mBAAmB;YACtB,GAAG,8BAA8B;YACjC,GAAG,gCAAc,CAAC,KAAK;YAEvB,qEAAqE;YACrE,6DAA6D;YAC7D,8EAA8E;YAC9E,qEAAqE;YACrE,mCAAmC,EAAE,MAAM;YAC3C,yCAAyC,EAAE,MAAM;YACjD,mCAAmC,EAAE,MAAM;YAC3C,4CAA4C,EAAE,MAAM;YACpD,qCAAqC,EAAE,MAAM;YAC7C,uCAAuC,EAAE,MAAM;YAC/C,8CAA8C,EAAE,MAAM;YACtD,0CAA0C,EAAE,MAAM;YAClD,yCAAyC,EAAE,MAAM;YACjD,wCAAwC,EAAE,MAAM;YAChD,mCAAmC,EAAE,MAAM;YAC3C,qCAAqC,EAAE,MAAM;YAC7C,iDAAiD,EAAE,MAAM;YACzD,kCAAkC,EAAE,MAAM;YAC1C,iCAAiC,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;YAC3D,sCAAsC,EAAE,MAAM;YAC9C,kDAAkD,EAAE,MAAM;YAC1D,2CAA2C,EAAE,MAAM;YACnD,kDAAkD,EAAE,MAAM;YAC1D,mDAAmD,EAAE,MAAM;YAC3D,kCAAkC,EAAE,MAAM;YAC1C,iDAAiD,EAAE,MAAM;YACzD,oCAAoC,EAAE,MAAM;YAC5C,8CAA8C,EAAE,MAAM;YACtD,0CAA0C,EAAE,MAAM;YAClD,oCAAoC,EAAE,MAAM;YAC5C,mDAAmD,EAAE,MAAM;YAC3D,+CAA+C,EAAE,MAAM;YACvD,mCAAmC,EAAE,MAAM;YAC3C,gDAAgD,EAAE,MAAM;YACxD,2DAA2D,EAAE,MAAM;YACnE,mCAAmC,EAAE,MAAM;YAC3C,4CAA4C,EAAE,MAAM;YACpD,4CAA4C,EAAE,KAAK;YACnD,cAAc,EAAE,KAAK;YACrB,iCAAiC,EAAE,CAAC,MAAM,EAAE,EAAE,iCAAiC,EAAE,IAAI,EAAE,CAAC;YAExF,qEAAqE;YACrE,wEAAwE;YACxE,qEAAqE;YACrE,oCAAoC,EAAE,OAAO;YAC7C,0CAA0C,EAAE,OAAO;YACnD,iCAAiC,EAAE,OAAO;YAC1C,mCAAmC,EAAE,OAAO;YAC5C,yCAAyC,EAAE,OAAO;YAClD,2CAA2C,EAAE;gBAC3C,OAAO;gBACP,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE;aAC1D;YACD,uCAAuC,EAAE,OAAO;YAChD,yCAAyC,EAAE,OAAO;YAClD,6CAA6C,EAAE,OAAO;YACtD,kCAAkC,EAAE,OAAO;YAC3C,iDAAiD,EAAE,OAAO;YAC1D,+CAA+C,EAAE,OAAO;YACxD,wCAAwC,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;YAC/E,8BAA8B,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC3D,0CAA0C,EAAE,OAAO;YACnD,kCAAkC,EAAE,OAAO;YAC3C,oCAAoC,EAAE,OAAO;YAC7C,mCAAmC,EAAE,OAAO;YAC5C,kEAAkE;YAClE,qEAAqE;YACrE,sEAAsE;YACtE,sEAAsE;YACtE,0DAA0D;YAC1D,sEAAsE;YACtE,mEAAmE;YACnE,qEAAqE;YACrE,mEAAmE;YACnE,8DAA8D;YAC9D,+BAA+B;YAC/B,4CAA4C,EAAE,KAAK;YACnD,gDAAgD,EAAE,OAAO;YAEzD,6DAA6D;YAC7D,kDAAkD,EAAE,KAAK;YACzD,sCAAsC,EAAE,KAAK;YAC7C,yCAAyC,EAAE,KAAK;YAChD,uCAAuC,EAAE,KAAK;YAC9C,+BAA+B,EAAE,KAAK;YACtC,yCAAyC,EAAE,KAAK;YAChD,kDAAkD,EAAE,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;YAE1F,8EAA8E;YAC9E,sCAAsC,EAAE;gBACtC,MAAM;gBACN;oBACE,QAAQ,EAAE,SAAS;oBACnB,MAAM,EAAE,CAAC,WAAW,CAAC;oBACrB,iBAAiB,EAAE,OAAO;oBAC1B,kBAAkB,EAAE,OAAO;iBAC5B;gBACD;oBACE,QAAQ,EAAE,UAAU;oBACpB,MAAM,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;oBACjD,iBAAiB,EAAE,OAAO;iBAC3B;gBACD,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE;gBAC5E;oBACE,QAAQ,EAAE,YAAY;oBACtB,SAAS,EAAE,CAAC,SAAS,CAAC;oBACtB,MAAM,EAAE,CAAC,WAAW,CAAC;oBACrB,iBAAiB,EAAE,OAAO;iBAC3B;gBACD,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE;gBAChD,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE;gBAChE,8EAA8E;gBAC9E,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,IAAI,EAAE;gBACnD,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;aACrC;YAED,wCAAwC,EAAE;gBACxC,OAAO;gBACP;oBACE,KAAK,EAAE;wBACL,MAAM,EAAE;4BACN,OAAO,EAAE,uDAAuD;4BAChE,OAAO,EAAE,QAAQ;yBAClB;wBACD,QAAQ,EAAE;4BACR,OAAO,EAAE,mEAAmE;4BAC5E,OAAO,EAAE,YAAY;yBACtB;wBACD,OAAO,EAAE;4BACP,OAAO,EAAE,yDAAyD;4BAClE,OAAO,EAAE,SAAS;yBACnB;wBACD,MAAM,EAAE;4BACN,OAAO,EAAE,uDAAuD;4BAChE,OAAO,EAAE,QAAQ;yBAClB;wBACD,MAAM,EAAE;4BACN,OAAO,EAAE,uDAAuD;4BAChE,OAAO,EAAE,QAAQ;yBAClB;wBACD,MAAM,EAAE;4BACN,OAAO,EAAE,uDAAuD;4BAChE,OAAO,EAAE,QAAQ;yBAClB;qBACF;iBACF;aACF;YAED,qEAAqE;YACrE,oCAAoC;YACpC,qEAAqE;YACrE,wCAAwC,EAAE,OAAO;YACjD,oCAAoC,EAAE;gBACpC,OAAO;gBACP,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE;aACxD;YACD,sCAAsC,EAAE,OAAO;YAC/C,wCAAwC,EAAE,OAAO;YACjD,oCAAoC,EAAE;gBACpC,OAAO;gBACP,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE;aACzD;YACD,0CAA0C,EAAE,OAAO;YACnD,iCAAiC,EAAE,OAAO;YAC1C,6CAA6C,EAAE,OAAO;YACtD,kCAAkC,EAAE,OAAO;YAC3C,qCAAqC,EAAE,OAAO;YAC9C,kCAAkC,EAAE,OAAO;YAC3C,8CAA8C,EAAE,OAAO;YACvD,yCAAyC,EAAE,OAAO;YAClD,8CAA8C,EAAE,OAAO;YACvD,mCAAmC,EAAE,OAAO;YAC5C,2DAA2D,EAAE,OAAO;YACpE,kDAAkD,EAAE,OAAO;YAC3D,8CAA8C,EAAE,OAAO;YACvD,kDAAkD,EAAE,OAAO;YAC3D,2CAA2C,EAAE,OAAO;YACpD,2CAA2C,EAAE,OAAO;YAEpD,qEAAqE;YACrE,8CAA8C;YAC9C,qEAAqE;YACrE,yFAAyF;YACzF,0FAA0F;YAC1F,yFAAyF;YACzF,yFAAyF;YACzF,oEAAoE;YACpE,yBAAyB,EAAE,OAAO;YAClC,wBAAwB,EAAE,OAAO;YACjC,oFAAoF;YACpF,qFAAqF;YACrF,wFAAwF;YACxF,0FAA0F;YAC1F,6FAA6F;YAC7F,wBAAwB,EAAE,MAAM;YAChC,+BAA+B,EAAE,OAAO;YACxC,6BAA6B,EAAE,OAAO;YACtC,qCAAqC,EAAE,OAAO;YAC9C,yDAAyD;YACzD,4BAA4B,EAAE,OAAO;YACrC,gBAAgB,EAAE;gBAChB,OAAO;gBACP;oBACE,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC;oBACjF,kBAAkB,EAAE,QAAQ;oBAC5B,WAAW,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE;iBACrD;aACF;YAED,qEAAqE;YACrE,SAAS;YACT,qEAAqE;YACrE,uBAAuB,EAAE,OAAO;YAEhC,qEAAqE;YACrE,yCAAyC;YACzC,qEAAqE;YACrE,uBAAuB,EAAE,OAAO;YAChC,yBAAyB,EAAE,OAAO;YAElC,qEAAqE;YACrE,uDAAuD;YACvD,kFAAkF;YAClF,uFAAuF;YACvF,qEAAqE;YACrE,sCAAsC,EAAE,OAAO;YAC/C,8BAA8B,EAAE,OAAO;YACvC,iCAAiC,EAAE,OAAO,EAAE,sCAAsC;YAClF,oCAAoC,EAAE,KAAK;YAC3C,mCAAmC,EAAE,KAAK;YAC1C,qCAAqC,EAAE,KAAK;YAC5C,yCAAyC,EAAE,KAAK;YAChD,kCAAkC,EAAE,KAAK;YACzC,iCAAiC,EAAE,KAAK;YACxC,+BAA+B,EAAE,KAAK;YACtC,yCAAyC,EAAE,KAAK;YAChD,4BAA4B,EAAE,KAAK;YACnC,gDAAgD,EAAE,KAAK;YACvD,yCAAyC,EAAE,KAAK;YAEhD,qEAAqE;YACrE,uCAAuC;YACvC,yEAAyE;YACzE,qEAAqE;YACrE,2BAA2B,EAAE,MAAM;YACnC,8BAA8B,EAAE,MAAM;YACtC,4BAA4B,EAAE,MAAM;YACpC,4BAA4B,EAAE,MAAM;YACpC,gCAAgC,EAAE,MAAM;YAExC,qEAAqE;YACrE,uBAAuB;YACvB,qEAAqE;YACrE,kBAAkB,EAAE,OAAO;YAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;YACxB,mBAAmB,EAAE,OAAO;YAC5B,KAAK,EAAE,OAAO;YACd,mBAAmB,EAAE,OAAO;YAC5B,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;YAC3B,cAAc,EAAE,OAAO;YACvB,aAAa,EAAE;gBACb,OAAO;gBACP,KAAK;gBACL,QAAQ;gBACR,QAAQ;gBACR,QAAQ;gBACR,QAAQ;gBACR,SAAS;gBACT,SAAS;gBACT,WAAW;gBACX,WAAW;aACZ;YACD,sBAAsB,EAAE,KAAK;YAC7B,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;YACxB,sBAAsB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;YACnC,YAAY,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;YACzB,YAAY,EAAE,OAAO;YACrB,WAAW,EAAE,OAAO;YACpB,gBAAgB,EAAE,OAAO;YACzB,YAAY,EAAE;gBACZ,OAAO;gBACP;oBACE,KAAK,EAAE;wBACL,MAAM;wBACN,KAAK;wBACL,SAAS;wBACT,QAAQ;wBACR,OAAO;wBACP,OAAO;wBACP,YAAY;wBACZ,OAAO;wBACP,UAAU;wBACV,OAAO;wBACP,QAAQ;wBACR,OAAO;wBACP,gBAAgB;wBAChB,SAAS;wBACT,SAAS;wBACT,YAAY;wBACZ,WAAW;wBACX,SAAS;qBACV;iBACF;aACF;YACD,aAAa,EAAE,OAAO;YACtB,UAAU,EAAE,KAAK;YACjB,mBAAmB,EAAE,KAAK;YAC1B,SAAS,EAAE,OAAO;YAClB,gBAAgB,EAAE,OAAO;YACzB,sBAAsB,EAAE,OAAO;YAC/B,iBAAiB,EAAE,KAAK;YACxB,iBAAiB,EAAE,OAAO;YAC1B,mBAAmB,EAAE,OAAO;YAC5B,uBAAuB,EAAE;gBACvB,OAAO;gBACP;oBACE,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,uCAAuC,EAAE;wBACrE;4BACE,IAAI,EAAE,QAAQ;4BACd,OAAO,EACL,4EAA4E;yBAC/E;wBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,uCAAuC,EAAE;qBACrE;iBACF;aACF;YACD,uFAAuF;YACvF,2EAA2E;YAC3E,sBAAsB,EAAE;gBACtB,OAAO;gBACP;oBACE,QAAQ,EACN,iGAAiG;oBACnG,OAAO,EACL,4QAA4Q;iBAC/Q;aACF;YACD,eAAe,EAAE,OAAO;YACxB,6BAA6B,EAAE,OAAO;YACtC,kBAAkB,EAAE,OAAO;YAC3B,eAAe,EAAE,OAAO;YACxB,sBAAsB,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;YAC9E,mBAAmB,EAAE,OAAO;YAC5B,kBAAkB,EAAE,OAAO;YAC3B,sBAAsB,EAAE,KAAK;YAC7B,mBAAmB,EAAE,OAAO;YAC5B,mBAAmB,EAAE,OAAO;YAC5B,QAAQ,EAAE,OAAO;YACjB,kBAAkB,EAAE,OAAO;YAC3B,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;YAC7B,uBAAuB,EAAE,OAAO;YAChC,cAAc,EAAE,OAAO;YACvB,sBAAsB,EAAE,OAAO;YAC/B,iBAAiB,EAAE,OAAO;YAC1B,aAAa,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;YACrC,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,OAAO;YACpB,IAAI,EAAE,OAAO;YAEb,oFAAoF;YACpF,mEAAmE;YACnE,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,KAAK;YACrB,UAAU,EAAE,KAAK;YACjB,iBAAiB,EAAE,KAAK;YACxB,SAAS,EAAE,KAAK;YAChB,YAAY,EAAE,KAAK;YACnB,0BAA0B,EAAE,KAAK;YACjC,eAAe,EAAE,KAAK;YACtB,yBAAyB,EAAE,KAAK;YAChC,yBAAyB,EAAE,KAAK;YAChC,oBAAoB,EAAE,KAAK;YAC3B,eAAe,EAAE,KAAK;YACtB,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,KAAK;YACX,iBAAiB,EAAE,KAAK;SACzB;KACF;IAED,wEAAwE;IACxE,sDAAsD;IACtD;QACE,KAAK,EAAE,SAAS;QAChB,eAAe,EAAE;YACf,MAAM,EAAE,qBAAqB;SAC9B;QACD,OAAO,EAAE;YACP,0BAA0B,EAAE,gCAAe;YAC3C,GAAG,EAAE,kBAAS;SACf;QACD,KAAK,EAAE;YACL,GAAI,gCAAe,CAAC,OAAO,CAAC,WAAW,CAAC,KAAqB;YAC7D,yBAAyB,EAAE,OAAO;YAClC,8CAA8C,EAAE,OAAO;SACxD;KACF;IAED,+EAA+E;IAC/E;QACE,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE;YACL,mCAAmC,EAAE,KAAK;YAC1C,mCAAmC,EAAE,KAAK;YAC1C,4CAA4C,EAAE,KAAK;YACnD,yCAAyC,EAAE,KAAK;YAChD,qCAAqC,EAAE,KAAK;YAC5C,uCAAuC,EAAE,KAAK;YAC9C,oCAAoC,EAAE,KAAK;YAC3C,sCAAsC,EAAE,KAAK;YAC7C,YAAY,EAAE,KAAK;YACnB,sBAAsB,EAAE,KAAK;SAC9B;KACF;IAED,wEAAwE;IACxE;QACE,KAAK,EAAE,CAAC,SAAS,CAAC;QAClB,eAAe,EAAE;YACf,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,QAAQ;SACrB;QACD,KAAK,EAAE;YACL,uCAAuC,EAAE,KAAK;SAC/C;KACF,CACF,CAAC;AACJ,CAAC","sourcesContent":["import angular from '@angular-eslint/eslint-plugin';\nimport angularTemplate from '@angular-eslint/eslint-plugin-template';\n// `@angular-eslint/template-parser` is a TypeScript-compiled ES module with\n// `__esModule: true` and only named exports — there is no `default`. A default\n// import via `__importDefault` resolves to `undefined`, silently dropping the\n// parser and letting ESLint fall back to espree (parser errors on every `.html`).\n// Namespace import preserves the parse/parseForESLint functions ESLint expects.\nimport * as angularTemplateParser from '@angular-eslint/template-parser';\nimport prettierConfig from 'eslint-config-prettier';\nimport importX from 'eslint-plugin-import-x';\nimport jsdoc from 'eslint-plugin-jsdoc';\nimport noUnsanitized from 'eslint-plugin-no-unsanitized';\nimport rxjsX from 'eslint-plugin-rxjs-x';\nimport security from 'eslint-plugin-security';\nimport tseslint, { type ConfigArray } from 'typescript-eslint';\n\nimport { tgoPlugin } from '../plugin';\n\n// `tseslint.configs.recommended` etc. are arrays of mixed config objects\n// (some carry `name`, some carry `rules`, etc.). Flatten their rule maps via\n// reduce; cast the result to a permissive record so the spread into the\n// strongly-typed `rules` block below doesn't leak unrelated config keys.\ntype RulesRecord = Record<string, unknown>;\n\nconst tseslintRecommended = tseslint.configs.recommended.reduce<RulesRecord>(\n (acc, cfg) => ({ ...acc, ...(cfg.rules ?? {}) }),\n {}\n);\nconst tseslintRecommendedTypeChecked = tseslint.configs.recommendedTypeChecked.reduce<RulesRecord>(\n (acc, cfg) => ({ ...acc, ...(cfg.rules ?? {}) }),\n {}\n);\n\nexport interface RecommendedOptions {\n /** Absolute path to the consumer repo root. Pass `import.meta.dirname`. */\n tsconfigRootDir: string;\n /** tsconfig path (relative to tsconfigRootDir). Default: 'tsconfig.json'. */\n project?: string;\n /** Glob for source TS files. Default: ['src/**\\/*.ts']. */\n tsFiles?: string[];\n /** Glob for HTML templates. Default: ['src/**\\/*.html']. */\n htmlFiles?: string[];\n /** Glob for spec files (relaxations applied). Default: ['src/**\\/*.spec.ts', 'src/**\\/*.integration.spec.ts']. */\n specFiles?: string[];\n}\n\n/**\n * Strict default ESLint flat-config preset for TGO Angular frontends.\n *\n * Type-aware rules (no-unsafe-*, restrict-*, no-floating-promises, etc.) are\n * kept at `warn` until consumer tsconfig moves to TS strict. Ratchet to error\n * after the strict tsconfig migration (Phase 1, Workstream 3).\n */\nexport function recommended(opts: RecommendedOptions): ConfigArray {\n const {\n tsconfigRootDir,\n project = 'tsconfig.json',\n tsFiles = ['src/**/*.ts'],\n htmlFiles = ['src/**/*.html'],\n specFiles = ['src/**/*.spec.ts', 'src/**/*.integration.spec.ts'],\n } = opts;\n\n return tseslint.config(\n // ── TypeScript files (*.ts) ──────────────────────────────────────────\n {\n files: tsFiles,\n languageOptions: {\n parser: tseslint.parser,\n parserOptions: {\n project,\n tsconfigRootDir,\n sourceType: 'module',\n },\n },\n settings: {\n 'import-x/resolver': {\n typescript: { project },\n node: true,\n },\n },\n plugins: {\n '@typescript-eslint': tseslint.plugin,\n '@angular-eslint': angular,\n 'import-x': importX,\n jsdoc,\n 'no-unsanitized': noUnsanitized,\n security,\n 'rxjs-x': rxjsX,\n },\n rules: {\n // Spread recommended + recommendedTypeChecked, then disable ESLint formatting\n // rules that conflict with Prettier. Prettier runs separately in consumer\n // pipelines (pre-commit / lint-staged / CI), not as an ESLint rule.\n ...tseslintRecommended,\n ...tseslintRecommendedTypeChecked,\n ...prettierConfig.rules,\n\n // ══════════════════════════════════════════════════════════════════\n // Type-aware rules — DEFERRED at warn until TS strict lands.\n // Cleanup PRs ratchet these to error after tsconfig.json gets `strict: true`.\n // ══════════════════════════════════════════════════════════════════\n '@typescript-eslint/no-unused-vars': 'warn',\n '@typescript-eslint/no-unsafe-assignment': 'warn',\n '@typescript-eslint/no-unsafe-call': 'warn',\n '@typescript-eslint/no-unsafe-member-access': 'warn',\n '@typescript-eslint/no-unsafe-return': 'warn',\n '@typescript-eslint/no-unsafe-argument': 'warn',\n '@typescript-eslint/no-unsafe-enum-comparison': 'warn',\n '@typescript-eslint/no-unsafe-unary-minus': 'warn',\n '@typescript-eslint/no-floating-promises': 'warn',\n '@typescript-eslint/no-misused-promises': 'warn',\n '@typescript-eslint/await-thenable': 'warn',\n '@typescript-eslint/only-throw-error': 'warn',\n '@typescript-eslint/prefer-promise-reject-errors': 'warn',\n '@typescript-eslint/require-await': 'warn',\n '@typescript-eslint/return-await': ['warn', 'in-try-catch'],\n '@typescript-eslint/no-base-to-string': 'warn',\n '@typescript-eslint/restrict-template-expressions': 'warn',\n '@typescript-eslint/restrict-plus-operands': 'warn',\n '@typescript-eslint/no-unnecessary-type-assertion': 'warn',\n '@typescript-eslint/no-redundant-type-constituents': 'warn',\n '@typescript-eslint/no-deprecated': 'warn',\n '@typescript-eslint/no-meaningless-void-operator': 'warn',\n '@typescript-eslint/prefer-readonly': 'warn',\n '@typescript-eslint/prefer-nullish-coalescing': 'warn',\n '@typescript-eslint/prefer-optional-chain': 'warn',\n '@typescript-eslint/prefer-includes': 'warn',\n '@typescript-eslint/prefer-string-starts-ends-with': 'warn',\n '@typescript-eslint/prefer-literal-enum-member': 'warn',\n '@typescript-eslint/no-mixed-enums': 'warn',\n '@typescript-eslint/switch-exhaustiveness-check': 'warn',\n '@typescript-eslint/use-unknown-in-catch-callback-variable': 'warn',\n '@typescript-eslint/unbound-method': 'warn',\n '@typescript-eslint/no-wrapper-object-types': 'warn',\n '@typescript-eslint/no-unsafe-function-type': 'off',\n 'dot-notation': 'off',\n '@typescript-eslint/dot-notation': ['warn', { allowIndexSignaturePropertyAccess: true }],\n\n // ══════════════════════════════════════════════════════════════════\n // Type-aware rules at error — purely syntactic, safe without TS strict.\n // ══════════════════════════════════════════════════════════════════\n '@typescript-eslint/no-explicit-any': 'error',\n '@typescript-eslint/no-non-null-assertion': 'error',\n '@typescript-eslint/no-namespace': 'error',\n '@typescript-eslint/no-misused-new': 'error',\n '@typescript-eslint/no-empty-object-type': 'error',\n '@typescript-eslint/triple-slash-reference': [\n 'error',\n { path: 'always', types: 'prefer-import', lib: 'always' },\n ],\n '@typescript-eslint/unified-signatures': 'error',\n '@typescript-eslint/prefer-function-type': 'error',\n '@typescript-eslint/prefer-namespace-keyword': 'error',\n '@typescript-eslint/prefer-for-of': 'error',\n '@typescript-eslint/adjacent-overload-signatures': 'error',\n '@typescript-eslint/consistent-type-assertions': 'error',\n '@typescript-eslint/no-inferrable-types': ['error', { ignoreParameters: true }],\n '@typescript-eslint/no-shadow': ['error', { hoist: 'all' }],\n '@typescript-eslint/no-unused-expressions': 'error',\n '@typescript-eslint/no-this-alias': 'error',\n '@typescript-eslint/no-for-in-array': 'error',\n '@typescript-eslint/ban-ts-comment': 'error',\n // consistent-type-imports — disabled preset-wide. The rule is not\n // Angular-aware: it converts constructor-injected service imports to\n // `import type { X }`, which then fails the Angular AOT compiler with\n // TS-992003 (\"No suitable injection token\") because Angular reads the\n // parameter type as a runtime DI token. The escape is one\n // `eslint-disable-next-line` comment per DI import, which scales with\n // the number of constructor-injected services in the codebase. Off\n // until either (a) consumer codebases migrate from constructor DI to\n // `inject()` everywhere — at which point the rule becomes safe and\n // valuable — or (b) we adopt a typescript-eslint variant that\n // recognises Angular DI sites.\n '@typescript-eslint/consistent-type-imports': 'off',\n '@typescript-eslint/no-import-type-side-effects': 'error',\n\n // High-friction rules — explicitly off (see plan rationale).\n '@typescript-eslint/explicit-function-return-type': 'off',\n '@typescript-eslint/no-empty-function': 'off',\n '@typescript-eslint/no-use-before-define': 'off',\n '@typescript-eslint/no-require-imports': 'off',\n '@typescript-eslint/array-type': 'off',\n '@typescript-eslint/parameter-properties': 'off',\n '@typescript-eslint/explicit-member-accessibility': ['off', { accessibility: 'explicit' }],\n\n // Naming convention — Angular-friendly, lenient. Land at warn, ratchet later.\n '@typescript-eslint/naming-convention': [\n 'warn',\n {\n selector: 'default',\n format: ['camelCase'],\n leadingUnderscore: 'allow',\n trailingUnderscore: 'allow',\n },\n {\n selector: 'variable',\n format: ['camelCase', 'UPPER_CASE', 'PascalCase'],\n leadingUnderscore: 'allow',\n },\n { selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' },\n {\n selector: 'memberLike',\n modifiers: ['private'],\n format: ['camelCase'],\n leadingUnderscore: 'allow',\n },\n { selector: 'typeLike', format: ['PascalCase'] },\n { selector: 'enumMember', format: ['PascalCase', 'UPPER_CASE'] },\n // API payloads commonly use snake_case — opt out of property naming entirely.\n { selector: 'objectLiteralProperty', format: null },\n { selector: 'import', format: null },\n ],\n\n '@typescript-eslint/no-restricted-types': [\n 'error',\n {\n types: {\n Object: {\n message: 'Avoid using the `Object` type. Did you mean `object`?',\n fixWith: 'object',\n },\n Function: {\n message: 'Avoid using the `Function` type. Prefer a specific function type.',\n fixWith: '() => void',\n },\n Boolean: {\n message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',\n fixWith: 'boolean',\n },\n Number: {\n message: 'Avoid using the `Number` type. Did you mean `number`?',\n fixWith: 'number',\n },\n String: {\n message: 'Avoid using the `String` type. Did you mean `string`?',\n fixWith: 'string',\n },\n Symbol: {\n message: 'Avoid using the `Symbol` type. Did you mean `symbol`?',\n fixWith: 'symbol',\n },\n },\n },\n ],\n\n // ══════════════════════════════════════════════════════════════════\n // Angular structural rules — error.\n // ══════════════════════════════════════════════════════════════════\n '@angular-eslint/component-class-suffix': 'error',\n '@angular-eslint/component-selector': [\n 'error',\n { type: 'element', prefix: 'tgo', style: 'kebab-case' },\n ],\n '@angular-eslint/contextual-lifecycle': 'error',\n '@angular-eslint/directive-class-suffix': 'error',\n '@angular-eslint/directive-selector': [\n 'error',\n { type: 'attribute', prefix: 'tgo', style: 'camelCase' },\n ],\n '@angular-eslint/no-conflicting-lifecycle': 'error',\n '@angular-eslint/no-input-rename': 'error',\n '@angular-eslint/no-inputs-metadata-property': 'error',\n '@angular-eslint/no-output-native': 'error',\n '@angular-eslint/no-output-on-prefix': 'error',\n '@angular-eslint/no-output-rename': 'error',\n '@angular-eslint/no-outputs-metadata-property': 'error',\n '@angular-eslint/use-lifecycle-interface': 'error',\n '@angular-eslint/use-pipe-transform-interface': 'error',\n '@angular-eslint/prefer-standalone': 'error',\n '@angular-eslint/prefer-on-push-component-change-detection': 'error',\n '@angular-eslint/use-component-view-encapsulation': 'error',\n '@angular-eslint/no-queries-metadata-property': 'error',\n '@angular-eslint/no-duplicates-in-metadata-arrays': 'error',\n '@angular-eslint/no-async-lifecycle-method': 'error',\n '@angular-eslint/no-empty-lifecycle-method': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Import discipline (eslint-plugin-import-x).\n // ══════════════════════════════════════════════════════════════════\n // PERF NOTE — full-repo lint with this rule enabled costs ~+45s wall and ~+1 GB peak RSS\n // (measured: 92.8s / 3.38 GB OFF vs 138.6s / 4.44 GB ON across 2,337 files). It walks the\n // full import graph and finds zero violations today. Kept active to preserve the rule as\n // part of the canonical rule set; revisit moving it to OXLint's fast path as part of the\n // toolchain decision (Phase 1, Workstream 1) rather than disabling.\n 'import-x/no-self-import': 'error',\n 'import-x/no-duplicates': 'error',\n // PERF NOTE — TIMING profile shows this rule at 64-75% of total rule execution time\n // (~1.1-1.3s per file). It walks every import looking for @deprecated JSDoc tags and\n // currently reports zero violations. Type-aware; ratchets to error with the rest of the\n // type-aware family after TS strict lands. Kept at warn rather than off so the rule stays\n // part of the canonical rule set; revisit migrating to OXLint's fast path with Workstream 1.\n 'import-x/no-deprecated': 'warn',\n 'import-x/no-relative-packages': 'error',\n 'import-x/no-mutable-exports': 'error',\n 'import-x/no-extraneous-dependencies': 'error',\n // Consumers carve out routing/lazy/config/stories paths.\n 'import-x/no-default-export': 'error',\n 'import-x/order': [\n 'error',\n {\n groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'type'],\n 'newlines-between': 'always',\n alphabetize: { order: 'asc', caseInsensitive: true },\n },\n ],\n\n // ══════════════════════════════════════════════════════════════════\n // JSDoc.\n // ══════════════════════════════════════════════════════════════════\n 'jsdoc/check-alignment': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Security: XSS guards (no-unsanitized).\n // ══════════════════════════════════════════════════════════════════\n 'no-unsanitized/method': 'error',\n 'no-unsanitized/property': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Security: cherry-picked from eslint-plugin-security.\n // Most rules in this plugin are Node-specific and noisy in browser code; only the\n // browser-relevant detectors are enabled. Plugin defaults explicitly turned off below.\n // ══════════════════════════════════════════════════════════════════\n 'security/detect-eval-with-expression': 'error',\n 'security/detect-unsafe-regex': 'error',\n 'security/detect-bidi-characters': 'error', // CVE-2021-42574 trojan-source guard.\n 'security/detect-non-literal-regexp': 'off',\n 'security/detect-pseudoRandomBytes': 'off',\n 'security/detect-non-literal-require': 'off',\n 'security/detect-non-literal-fs-filename': 'off',\n 'security/detect-object-injection': 'off',\n 'security/detect-buffer-noassert': 'off',\n 'security/detect-child-process': 'off',\n 'security/detect-disable-mustache-escape': 'off',\n 'security/detect-new-buffer': 'off',\n 'security/detect-no-csrf-before-method-override': 'off',\n 'security/detect-possible-timing-attacks': 'off',\n\n // ══════════════════════════════════════════════════════════════════\n // RxJS hygiene (eslint-plugin-rxjs-x).\n // Some rules use type info; land at warn until TS strict, ratchet after.\n // ══════════════════════════════════════════════════════════════════\n 'rxjs-x/no-async-subscribe': 'warn',\n 'rxjs-x/no-implicit-any-catch': 'warn',\n 'rxjs-x/no-nested-subscribe': 'warn',\n 'rxjs-x/no-unsafe-takeuntil': 'warn',\n 'rxjs-x/no-ignored-subscription': 'warn',\n\n // ══════════════════════════════════════════════════════════════════\n // Core ESLint — error.\n // ══════════════════════════════════════════════════════════════════\n 'arrow-body-style': 'error',\n complexity: ['warn', 15],\n 'constructor-super': 'error',\n curly: 'error',\n 'default-case-last': 'error',\n eqeqeq: ['error', 'always'],\n 'guard-for-in': 'error',\n 'id-denylist': [\n 'error',\n 'any',\n 'Number',\n 'number',\n 'String',\n 'string',\n 'Boolean',\n 'boolean',\n 'Undefined',\n 'undefined',\n ],\n 'max-classes-per-file': 'off',\n 'max-depth': ['warn', 4],\n 'max-nested-callbacks': ['warn', 3],\n 'max-params': ['warn', 5],\n 'no-bitwise': 'error',\n 'no-caller': 'error',\n 'no-cond-assign': 'error',\n 'no-console': [\n 'error',\n {\n allow: [\n 'warn',\n 'dir',\n 'timeLog',\n 'assert',\n 'clear',\n 'count',\n 'countReset',\n 'group',\n 'groupEnd',\n 'table',\n 'dirxml',\n 'error',\n 'groupCollapsed',\n 'Console',\n 'profile',\n 'profileEnd',\n 'timeStamp',\n 'context',\n ],\n },\n ],\n 'no-debugger': 'error',\n 'no-empty': 'off',\n 'no-empty-function': 'off',\n 'no-eval': 'error',\n 'no-fallthrough': 'error',\n 'no-implicit-coercion': 'error',\n 'no-invalid-this': 'off',\n 'no-new-wrappers': 'error',\n 'no-param-reassign': 'error',\n 'no-restricted-imports': [\n 'error',\n {\n paths: [\n { name: 'rxjs/Rx', message: 'Use the rxjs barrel (`rxjs`) instead.' },\n {\n name: 'lodash',\n message:\n 'Import per-method from lodash (e.g., `lodash/cloneDeep`) for tree-shaking.',\n },\n { name: 'moment', message: 'Use date-fns (already a project dep).' },\n ],\n },\n ],\n // Block direct DomSanitizer.bypassSecurityTrust* calls — production callers should use\n // sanitization wrapper pipes. Consumers carve out the wrappers themselves.\n 'no-restricted-syntax': [\n 'error',\n {\n selector:\n 'CallExpression[callee.property.name=/^bypassSecurityTrust(Html|Script|Url|ResourceUrl|Style)$/]',\n message:\n 'Use the bypass-sanitization-{html,url}.pipe.ts wrappers in src/@testgorilla/pipes instead of calling DomSanitizer.bypassSecurityTrust* directly. If a TS-side bypass is genuinely required, add an inline eslint-disable-next-line with a SECURITY comment explaining why.',\n },\n ],\n 'no-script-url': 'error',\n 'no-template-curly-in-string': 'error',\n 'no-throw-literal': 'error',\n 'no-undef-init': 'error',\n 'no-underscore-dangle': ['error', { allow: ['_state'], allowAfterThis: true }],\n 'no-unsafe-finally': 'error',\n 'no-unused-labels': 'error',\n 'no-use-before-define': 'off',\n 'no-useless-concat': 'error',\n 'no-useless-return': 'error',\n 'no-var': 'error',\n 'object-shorthand': 'error',\n 'one-var': ['error', 'never'],\n 'prefer-arrow-callback': 'error',\n 'prefer-const': 'error',\n 'prefer-object-spread': 'error',\n 'prefer-template': 'error',\n 'quote-props': ['error', 'as-needed'],\n radix: 'error',\n 'use-isnan': 'error',\n yoda: 'error',\n\n // ── Off — Prettier owns formatting. eslint-config-prettier disables most of these;\n // listing explicitly overrides any preset that re-enables them.\n 'arrow-parens': 'off',\n 'brace-style': 'off',\n 'comma-dangle': 'off',\n 'eol-last': 'off',\n 'linebreak-style': 'off',\n 'max-len': 'off',\n 'new-parens': 'off',\n 'newline-per-chained-call': 'off',\n 'no-extra-semi': 'off',\n 'no-irregular-whitespace': 'off',\n 'no-multiple-empty-lines': 'off',\n 'no-trailing-spaces': 'off',\n 'padded-blocks': 'off',\n quotes: 'off',\n semi: 'off',\n 'space-in-parens': 'off',\n },\n },\n\n // ── HTML template files (*.html) ─────────────────────────────────────\n // a11y rule set is deferred to a separate workstream.\n {\n files: htmlFiles,\n languageOptions: {\n parser: angularTemplateParser,\n },\n plugins: {\n '@angular-eslint/template': angularTemplate,\n tgo: tgoPlugin,\n },\n rules: {\n ...(angularTemplate.configs.recommended.rules as RulesRecord),\n 'tgo/require-data-testid': 'error',\n '@angular-eslint/template/prefer-control-flow': 'error',\n },\n },\n\n // ── Spec files (*.spec.ts, *.integration.spec.ts) — relax type/style rules ──\n {\n files: specFiles,\n rules: {\n '@typescript-eslint/unbound-method': 'off',\n '@typescript-eslint/no-unsafe-call': 'off',\n '@typescript-eslint/no-unsafe-member-access': 'off',\n '@typescript-eslint/no-unsafe-assignment': 'off',\n '@typescript-eslint/no-unsafe-return': 'off',\n '@typescript-eslint/no-unsafe-argument': 'off',\n '@typescript-eslint/no-explicit-any': 'off',\n '@typescript-eslint/naming-convention': 'off',\n 'max-params': 'off',\n 'max-nested-callbacks': 'off',\n },\n },\n\n // ── JS files ─────────────────────────────────────────────────────────\n {\n files: ['**/*.js'],\n languageOptions: {\n ecmaVersion: 2020,\n sourceType: 'module',\n },\n rules: {\n '@typescript-eslint/no-require-imports': 'off',\n },\n }\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../../../../packages/tgo-linting/src/configs/recommended.ts"],"names":[],"mappings":"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","sourcesContent":["import angular from '@angular-eslint/eslint-plugin';\nimport angularTemplate from '@angular-eslint/eslint-plugin-template';\n// `@angular-eslint/template-parser` is a TypeScript-compiled ES module with\n// `__esModule: true` and only named exports — there is no `default`. A default\n// import via `__importDefault` resolves to `undefined`, silently dropping the\n// parser and letting ESLint fall back to espree (parser errors on every `.html`).\n// Namespace import preserves the parse/parseForESLint functions ESLint expects.\nimport * as angularTemplateParser from '@angular-eslint/template-parser';\nimport prettierConfig from 'eslint-config-prettier';\nimport importX from 'eslint-plugin-import-x';\nimport jsdoc from 'eslint-plugin-jsdoc';\nimport noUnsanitized from 'eslint-plugin-no-unsanitized';\nimport rxjsX from 'eslint-plugin-rxjs-x';\nimport security from 'eslint-plugin-security';\nimport tseslint, { type ConfigArray } from 'typescript-eslint';\n\nimport { tgoPlugin } from '../plugin';\n\n// `tseslint.configs.recommended` etc. are arrays of mixed config objects\n// (some carry `name`, some carry `rules`, etc.). Flatten their rule maps via\n// reduce; cast the result to a permissive record so the spread into the\n// strongly-typed `rules` block below doesn't leak unrelated config keys.\ntype RulesRecord = Record<string, unknown>;\n\nconst tseslintRecommended = tseslint.configs.recommended.reduce<RulesRecord>(\n (acc, cfg) => ({ ...acc, ...(cfg.rules ?? {}) }),\n {}\n);\nconst tseslintRecommendedTypeChecked = tseslint.configs.recommendedTypeChecked.reduce<RulesRecord>(\n (acc, cfg) => ({ ...acc, ...(cfg.rules ?? {}) }),\n {}\n);\n\nexport interface RecommendedOptions {\n /** Absolute path to the consumer repo root. Pass `import.meta.dirname`. */\n tsconfigRootDir: string;\n /** tsconfig path (relative to tsconfigRootDir). Default: 'tsconfig.json'. */\n project?: string;\n /** Glob for source TS files. Default: ['src/**\\/*.ts']. */\n tsFiles?: string[];\n /** Glob for HTML templates. Default: ['src/**\\/*.html']. */\n htmlFiles?: string[];\n /** Glob for spec files (relaxations applied). Default: ['src/**\\/*.spec.ts', 'src/**\\/*.integration.spec.ts']. */\n specFiles?: string[];\n}\n\n/**\n * Strict default ESLint flat-config preset for TGO Angular frontends.\n *\n * Type-aware rules (no-unsafe-*, restrict-*, no-floating-promises, etc.) are\n * at `error`. The previously-deferred warn severities were ratcheted to error\n * after the strict tsconfig migration landed in consumer codebases. Two rules\n * remain explicitly relaxed in the preset:\n * - `@typescript-eslint/consistent-type-imports` (off — Angular DI conflict)\n * - `@angular-eslint/use-component-view-encapsulation` (off — separate\n * styling refactor workstream)\n * See the inline comments at each rule for full rationale.\n *\n * The spec/mock files block (default glob: *.spec.ts + *.integration.spec.ts\n * + *.mock.ts + *.mocks.ts) relaxes type-aware family rules and a few others\n * to match the idiomatic test-code shape (bracket access, fire-trigger\n * subscribes, mock literals with `any` typing).\n */\nexport function recommended(opts: RecommendedOptions): ConfigArray {\n const {\n tsconfigRootDir,\n project = 'tsconfig.json',\n tsFiles = ['src/**/*.ts'],\n htmlFiles = ['src/**/*.html'],\n specFiles = [\n 'src/**/*.spec.ts',\n 'src/**/*.integration.spec.ts',\n 'src/**/*.mock.ts',\n 'src/**/*.mocks.ts',\n ],\n } = opts;\n\n return tseslint.config(\n // ── TypeScript files (*.ts) ──────────────────────────────────────────\n {\n files: tsFiles,\n languageOptions: {\n parser: tseslint.parser,\n parserOptions: {\n project,\n tsconfigRootDir,\n sourceType: 'module',\n },\n },\n settings: {\n 'import-x/resolver': {\n typescript: { project },\n node: true,\n },\n },\n plugins: {\n '@typescript-eslint': tseslint.plugin,\n '@angular-eslint': angular,\n 'import-x': importX,\n jsdoc,\n 'no-unsanitized': noUnsanitized,\n security,\n 'rxjs-x': rxjsX,\n },\n rules: {\n // Spread recommended + recommendedTypeChecked, then disable ESLint formatting\n // rules that conflict with Prettier. Prettier runs separately in consumer\n // pipelines (pre-commit / lint-staged / CI), not as an ESLint rule.\n ...tseslintRecommended,\n ...tseslintRecommendedTypeChecked,\n ...prettierConfig.rules,\n\n // ══════════════════════════════════════════════════════════════════\n // Type-aware rules — ERROR (ratcheted from warn after TS strict landed\n // in consumer codebases).\n // ══════════════════════════════════════════════════════════════════\n // `_`-prefix is the conventional opt-out for intentionally-unused\n // identifiers in TypeScript (matches the `noUnusedParameters` compiler\n // option's behavior). Mock/stub methods that need a signature-compatible\n // parameter but ignore the value (e.g. `configure(_config?: …) {}`),\n // destructured rest collectors (`const { _internal: _, ...rest } = obj`),\n // and `catch (_e: unknown)` blocks all benefit. Production code can't\n // accidentally hide real unused names — pick a different prefix.\n '@typescript-eslint/no-unused-vars': [\n 'error',\n {\n argsIgnorePattern: '^_',\n varsIgnorePattern: '^_',\n caughtErrorsIgnorePattern: '^_',\n },\n ],\n '@typescript-eslint/no-unsafe-assignment': 'error',\n '@typescript-eslint/no-unsafe-call': 'error',\n '@typescript-eslint/no-unsafe-member-access': 'error',\n '@typescript-eslint/no-unsafe-return': 'error',\n '@typescript-eslint/no-unsafe-argument': 'error',\n '@typescript-eslint/no-unsafe-enum-comparison': 'error',\n '@typescript-eslint/no-unsafe-unary-minus': 'error',\n '@typescript-eslint/no-floating-promises': 'error',\n '@typescript-eslint/no-misused-promises': 'error',\n '@typescript-eslint/await-thenable': 'error',\n '@typescript-eslint/only-throw-error': 'error',\n '@typescript-eslint/prefer-promise-reject-errors': 'error',\n '@typescript-eslint/require-await': 'error',\n '@typescript-eslint/return-await': ['error', 'in-try-catch'],\n '@typescript-eslint/no-base-to-string': 'error',\n '@typescript-eslint/restrict-template-expressions': 'error',\n '@typescript-eslint/restrict-plus-operands': 'error',\n '@typescript-eslint/no-unnecessary-type-assertion': 'error',\n '@typescript-eslint/no-redundant-type-constituents': 'error',\n '@typescript-eslint/no-deprecated': 'error',\n '@typescript-eslint/no-meaningless-void-operator': 'error',\n '@typescript-eslint/prefer-readonly': 'error',\n '@typescript-eslint/prefer-nullish-coalescing': 'error',\n '@typescript-eslint/prefer-optional-chain': 'error',\n '@typescript-eslint/prefer-includes': 'error',\n '@typescript-eslint/prefer-string-starts-ends-with': 'error',\n '@typescript-eslint/prefer-literal-enum-member': 'error',\n '@typescript-eslint/no-mixed-enums': 'error',\n '@typescript-eslint/switch-exhaustiveness-check': 'error',\n '@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',\n '@typescript-eslint/unbound-method': 'error',\n '@typescript-eslint/no-wrapper-object-types': 'error',\n '@typescript-eslint/no-unsafe-function-type': 'off',\n 'dot-notation': 'off',\n '@typescript-eslint/dot-notation': ['error', { allowIndexSignaturePropertyAccess: true }],\n\n // ══════════════════════════════════════════════════════════════════\n // Type-aware rules at error — purely syntactic, safe without TS strict.\n // ══════════════════════════════════════════════════════════════════\n '@typescript-eslint/no-explicit-any': 'error',\n '@typescript-eslint/no-non-null-assertion': 'error',\n '@typescript-eslint/no-namespace': 'error',\n '@typescript-eslint/no-misused-new': 'error',\n '@typescript-eslint/no-empty-object-type': 'error',\n '@typescript-eslint/triple-slash-reference': [\n 'error',\n { path: 'always', types: 'prefer-import', lib: 'always' },\n ],\n '@typescript-eslint/unified-signatures': 'error',\n '@typescript-eslint/prefer-function-type': 'error',\n '@typescript-eslint/prefer-namespace-keyword': 'error',\n '@typescript-eslint/prefer-for-of': 'error',\n '@typescript-eslint/adjacent-overload-signatures': 'error',\n '@typescript-eslint/consistent-type-assertions': 'error',\n '@typescript-eslint/no-inferrable-types': ['error', { ignoreParameters: true }],\n '@typescript-eslint/no-shadow': ['error', { hoist: 'all' }],\n '@typescript-eslint/no-unused-expressions': 'error',\n '@typescript-eslint/no-this-alias': 'error',\n '@typescript-eslint/no-for-in-array': 'error',\n '@typescript-eslint/ban-ts-comment': 'error',\n // consistent-type-imports — disabled preset-wide. The rule is not\n // Angular-aware: it converts constructor-injected service imports to\n // `import type { X }`, which then fails the Angular AOT compiler with\n // TS-992003 (\"No suitable injection token\") because Angular reads the\n // parameter type as a runtime DI token. The escape is one\n // `eslint-disable-next-line` comment per DI import, which scales with\n // the number of constructor-injected services in the codebase. Off\n // until either (a) consumer codebases migrate from constructor DI to\n // `inject()` everywhere — at which point the rule becomes safe and\n // valuable — or (b) we adopt a typescript-eslint variant that\n // recognises Angular DI sites.\n '@typescript-eslint/consistent-type-imports': 'off',\n '@typescript-eslint/no-import-type-side-effects': 'error',\n\n // High-friction rules — explicitly off (see plan rationale).\n '@typescript-eslint/explicit-function-return-type': 'off',\n '@typescript-eslint/no-empty-function': 'off',\n '@typescript-eslint/no-use-before-define': 'off',\n '@typescript-eslint/no-require-imports': 'off',\n '@typescript-eslint/array-type': 'off',\n '@typescript-eslint/parameter-properties': 'off',\n '@typescript-eslint/explicit-member-accessibility': ['off', { accessibility: 'explicit' }],\n\n // Naming convention — Angular-friendly, lenient. Error severity (ratcheted\n // from warn). Selectors below opt out of naming enforcement for the\n // identifier kinds that legitimately mirror the snake_case shape of\n // TestGorilla's backend API (DTOs, destructured server responses,\n // class fields that proxy API field names, Quill keyboard-shortcut /\n // language object-literal method keys like `Cmd-Z` or `c++`).\n // Last-matching-selector-wins, so the additions go at the tail.\n '@typescript-eslint/naming-convention': [\n 'error',\n {\n selector: 'default',\n format: ['camelCase'],\n leadingUnderscore: 'allow',\n trailingUnderscore: 'allow',\n },\n {\n selector: 'variable',\n format: ['camelCase', 'UPPER_CASE', 'PascalCase'],\n leadingUnderscore: 'allow',\n },\n { selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' },\n {\n selector: 'memberLike',\n modifiers: ['private'],\n format: ['camelCase'],\n leadingUnderscore: 'allow',\n },\n { selector: 'typeLike', format: ['PascalCase'] },\n { selector: 'enumMember', format: ['PascalCase', 'UPPER_CASE'] },\n // API payloads commonly use snake_case — opt out of property naming entirely.\n { selector: 'objectLiteralProperty', format: null },\n { selector: 'import', format: null },\n // Interface / type members modelling API shape.\n { selector: 'typeProperty', format: null },\n // DTO classes + UPPER_CASE static const-like fields + PascalCase class-field\n // re-exports of types/enums to templates.\n { selector: 'classProperty', format: null, leadingUnderscore: 'allow' },\n // `const { foo_bar } = result;` destructured locals/parameters keep API names.\n { selector: 'variable', modifiers: ['destructured'], format: null },\n { selector: 'parameter', modifiers: ['destructured'], format: null },\n // Quill keyboard shortcuts (`Cmd-Z`, `Ctrl-Shift-K`) and language keys (`c++`, `c#`).\n { selector: 'objectLiteralMethod', format: null },\n ],\n\n '@typescript-eslint/no-restricted-types': [\n 'error',\n {\n types: {\n Object: {\n message: 'Avoid using the `Object` type. Did you mean `object`?',\n fixWith: 'object',\n },\n Function: {\n message: 'Avoid using the `Function` type. Prefer a specific function type.',\n fixWith: '() => void',\n },\n Boolean: {\n message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',\n fixWith: 'boolean',\n },\n Number: {\n message: 'Avoid using the `Number` type. Did you mean `number`?',\n fixWith: 'number',\n },\n String: {\n message: 'Avoid using the `String` type. Did you mean `string`?',\n fixWith: 'string',\n },\n Symbol: {\n message: 'Avoid using the `Symbol` type. Did you mean `symbol`?',\n fixWith: 'symbol',\n },\n },\n },\n ],\n\n // ══════════════════════════════════════════════════════════════════\n // Angular structural rules — error.\n // ══════════════════════════════════════════════════════════════════\n '@angular-eslint/component-class-suffix': 'error',\n '@angular-eslint/component-selector': [\n 'error',\n { type: 'element', prefix: 'tgo', style: 'kebab-case' },\n ],\n '@angular-eslint/contextual-lifecycle': 'error',\n '@angular-eslint/directive-class-suffix': 'error',\n '@angular-eslint/directive-selector': [\n 'error',\n { type: 'attribute', prefix: 'tgo', style: 'camelCase' },\n ],\n '@angular-eslint/no-conflicting-lifecycle': 'error',\n '@angular-eslint/no-input-rename': 'error',\n '@angular-eslint/no-inputs-metadata-property': 'error',\n '@angular-eslint/no-output-native': 'error',\n '@angular-eslint/no-output-on-prefix': 'error',\n '@angular-eslint/no-output-rename': 'error',\n '@angular-eslint/no-outputs-metadata-property': 'error',\n '@angular-eslint/use-lifecycle-interface': 'error',\n '@angular-eslint/use-pipe-transform-interface': 'error',\n '@angular-eslint/prefer-standalone': 'error',\n '@angular-eslint/prefer-on-push-component-change-detection': 'error',\n // use-component-view-encapsulation — off in the preset. Re-enabling\n // requires per-component audit of every `ViewEncapsulation.None` site\n // (third-party DOM targets, global content-projection slots, intentional\n // style leaks) and a refactor for the accidental ones. That work belongs\n // in a dedicated styling-focused workstream in each consumer codebase,\n // not in this preset's strict default. Consumers can override to\n // `error` locally if they want to gate on it sooner. TODO: revisit\n // when at least one consumer ships the per-component audit.\n '@angular-eslint/use-component-view-encapsulation': 'off',\n '@angular-eslint/no-queries-metadata-property': 'error',\n '@angular-eslint/no-duplicates-in-metadata-arrays': 'error',\n '@angular-eslint/no-async-lifecycle-method': 'error',\n '@angular-eslint/no-empty-lifecycle-method': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Import discipline (eslint-plugin-import-x).\n // ══════════════════════════════════════════════════════════════════\n // PERF NOTE — full-repo lint with this rule enabled costs ~+45s wall and ~+1 GB peak RSS\n // (measured: 92.8s / 3.38 GB OFF vs 138.6s / 4.44 GB ON across 2,337 files). It walks the\n // full import graph and finds zero violations today. Kept active to preserve the rule as\n // part of the canonical rule set; revisit moving it to OXLint's fast path as part of the\n // toolchain decision (Phase 1, Workstream 1) rather than disabling.\n 'import-x/no-self-import': 'error',\n 'import-x/no-duplicates': 'error',\n // PERF NOTE — TIMING profile shows this rule at 64-75% of total rule execution time\n // (~1.1-1.3s per file). It walks every import looking for @deprecated JSDoc tags. Ratcheted\n // to error along with the rest of the type-aware family after TS strict landed. Revisit\n // migrating to OXLint's fast path with Workstream 1 if total lint time becomes a concern.\n 'import-x/no-deprecated': 'error',\n 'import-x/no-relative-packages': 'error',\n 'import-x/no-mutable-exports': 'error',\n 'import-x/no-extraneous-dependencies': 'error',\n // Consumers carve out routing/lazy/config/stories paths.\n 'import-x/no-default-export': 'error',\n 'import-x/order': [\n 'error',\n {\n groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'type'],\n 'newlines-between': 'always',\n alphabetize: { order: 'asc', caseInsensitive: true },\n },\n ],\n\n // ══════════════════════════════════════════════════════════════════\n // JSDoc.\n // ══════════════════════════════════════════════════════════════════\n 'jsdoc/check-alignment': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Security: XSS guards (no-unsanitized).\n // ══════════════════════════════════════════════════════════════════\n 'no-unsanitized/method': 'error',\n 'no-unsanitized/property': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Security: cherry-picked from eslint-plugin-security.\n // Most rules in this plugin are Node-specific and noisy in browser code; only the\n // browser-relevant detectors are enabled. Plugin defaults explicitly turned off below.\n // ══════════════════════════════════════════════════════════════════\n 'security/detect-eval-with-expression': 'error',\n 'security/detect-unsafe-regex': 'error',\n 'security/detect-bidi-characters': 'error', // CVE-2021-42574 trojan-source guard.\n 'security/detect-non-literal-regexp': 'off',\n 'security/detect-pseudoRandomBytes': 'off',\n 'security/detect-non-literal-require': 'off',\n 'security/detect-non-literal-fs-filename': 'off',\n 'security/detect-object-injection': 'off',\n 'security/detect-buffer-noassert': 'off',\n 'security/detect-child-process': 'off',\n 'security/detect-disable-mustache-escape': 'off',\n 'security/detect-new-buffer': 'off',\n 'security/detect-no-csrf-before-method-override': 'off',\n 'security/detect-possible-timing-attacks': 'off',\n\n // ══════════════════════════════════════════════════════════════════\n // RxJS hygiene (eslint-plugin-rxjs-x). Error severity (ratcheted from\n // warn after TS strict landed). All five are real-bug-class rules\n // (async-in-subscribe, untyped catch in pipe, nested subscribes that\n // should be flatMap, completer-not-last, leaking subscriptions).\n // ══════════════════════════════════════════════════════════════════\n 'rxjs-x/no-async-subscribe': 'error',\n 'rxjs-x/no-implicit-any-catch': 'error',\n 'rxjs-x/no-nested-subscribe': 'error',\n 'rxjs-x/no-unsafe-takeuntil': 'error',\n 'rxjs-x/no-ignored-subscription': 'error',\n\n // ══════════════════════════════════════════════════════════════════\n // Core ESLint — error.\n // ══════════════════════════════════════════════════════════════════\n 'arrow-body-style': 'error',\n complexity: ['error', 15],\n 'constructor-super': 'error',\n curly: 'error',\n 'default-case-last': 'error',\n eqeqeq: ['error', 'always'],\n 'guard-for-in': 'error',\n 'id-denylist': [\n 'error',\n 'any',\n 'Number',\n 'number',\n 'String',\n 'string',\n 'Boolean',\n 'boolean',\n 'Undefined',\n 'undefined',\n ],\n 'max-classes-per-file': 'off',\n 'max-depth': ['error', 4],\n 'max-nested-callbacks': ['error', 3],\n 'max-params': ['error', 5],\n 'no-bitwise': 'error',\n 'no-caller': 'error',\n 'no-cond-assign': 'error',\n 'no-console': [\n 'error',\n {\n allow: [\n 'warn',\n 'dir',\n 'timeLog',\n 'assert',\n 'clear',\n 'count',\n 'countReset',\n 'group',\n 'groupEnd',\n 'table',\n 'dirxml',\n 'error',\n 'groupCollapsed',\n 'Console',\n 'profile',\n 'profileEnd',\n 'timeStamp',\n 'context',\n ],\n },\n ],\n 'no-debugger': 'error',\n 'no-empty': 'off',\n 'no-empty-function': 'off',\n 'no-eval': 'error',\n 'no-fallthrough': 'error',\n 'no-implicit-coercion': 'error',\n 'no-invalid-this': 'off',\n 'no-new-wrappers': 'error',\n 'no-param-reassign': 'error',\n 'no-restricted-imports': [\n 'error',\n {\n paths: [\n { name: 'rxjs/Rx', message: 'Use the rxjs barrel (`rxjs`) instead.' },\n {\n name: 'lodash',\n message:\n 'Import per-method from lodash (e.g., `lodash/cloneDeep`) for tree-shaking.',\n },\n { name: 'moment', message: 'Use date-fns (already a project dep).' },\n ],\n },\n ],\n // Block direct DomSanitizer.bypassSecurityTrust* calls — production callers should use\n // sanitization wrapper pipes. Consumers carve out the wrappers themselves.\n 'no-restricted-syntax': [\n 'error',\n {\n selector:\n 'CallExpression[callee.property.name=/^bypassSecurityTrust(Html|Script|Url|ResourceUrl|Style)$/]',\n message:\n 'Use the bypass-sanitization-{html,url}.pipe.ts wrappers in src/@testgorilla/pipes instead of calling DomSanitizer.bypassSecurityTrust* directly. If a TS-side bypass is genuinely required, add an inline eslint-disable-next-line with a SECURITY comment explaining why.',\n },\n ],\n 'no-script-url': 'error',\n 'no-template-curly-in-string': 'error',\n 'no-throw-literal': 'error',\n 'no-undef-init': 'error',\n 'no-underscore-dangle': ['error', { allow: ['_state'], allowAfterThis: true }],\n 'no-unsafe-finally': 'error',\n 'no-unused-labels': 'error',\n 'no-use-before-define': 'off',\n 'no-useless-concat': 'error',\n 'no-useless-return': 'error',\n 'no-var': 'error',\n 'object-shorthand': 'error',\n 'one-var': ['error', 'never'],\n 'prefer-arrow-callback': 'error',\n 'prefer-const': 'error',\n 'prefer-object-spread': 'error',\n 'prefer-template': 'error',\n 'quote-props': ['error', 'as-needed'],\n radix: 'error',\n 'use-isnan': 'error',\n yoda: 'error',\n\n // ── Off — Prettier owns formatting. eslint-config-prettier disables most of these;\n // listing explicitly overrides any preset that re-enables them.\n 'arrow-parens': 'off',\n 'brace-style': 'off',\n 'comma-dangle': 'off',\n 'eol-last': 'off',\n 'linebreak-style': 'off',\n 'max-len': 'off',\n 'new-parens': 'off',\n 'newline-per-chained-call': 'off',\n 'no-extra-semi': 'off',\n 'no-irregular-whitespace': 'off',\n 'no-multiple-empty-lines': 'off',\n 'no-trailing-spaces': 'off',\n 'padded-blocks': 'off',\n quotes: 'off',\n semi: 'off',\n 'space-in-parens': 'off',\n },\n },\n\n // ── HTML template files (*.html) ─────────────────────────────────────\n // a11y rule set is deferred to a separate workstream.\n {\n files: htmlFiles,\n languageOptions: {\n parser: angularTemplateParser,\n },\n plugins: {\n '@angular-eslint/template': angularTemplate,\n tgo: tgoPlugin,\n },\n rules: {\n ...(angularTemplate.configs.recommended.rules as RulesRecord),\n 'tgo/require-data-testid': 'error',\n '@angular-eslint/template/prefer-control-flow': 'error',\n },\n },\n\n // ── Spec / mock files (default glob: *.spec.ts, *.integration.spec.ts,\n // *.mock.ts, *.mocks.ts) — relax type-aware and a few style rules to\n // match the idiomatic test-code shape (bracket access for production\n // internals, fire-trigger subscribes that Jest cleans up via test\n // isolation, mock literals with `any`-shaped fixtures, snake_case API\n // field names re-used in fixture object literals). Also allows `ui-*`\n // selectors for mocks that substitute Canopy UI library components. ──\n {\n files: specFiles,\n rules: {\n '@typescript-eslint/unbound-method': 'off',\n '@typescript-eslint/no-unsafe-call': 'off',\n '@typescript-eslint/no-unsafe-member-access': 'off',\n '@typescript-eslint/no-unsafe-assignment': 'off',\n '@typescript-eslint/no-unsafe-return': 'off',\n '@typescript-eslint/no-unsafe-argument': 'off',\n '@typescript-eslint/no-explicit-any': 'off',\n '@typescript-eslint/naming-convention': 'off',\n 'max-params': 'off',\n 'max-nested-callbacks': 'off',\n // dot-notation: rule's autofix converts `service['privateField']` →\n // `service.privateField`, which trips TS access-modifier checks\n // (TS2341/TS2445) and/or no-underscore-dangle on `_`-prefixed\n // internals. Bracket access is the standard idiom for reaching\n // production internals from tests; the noise is purely cosmetic.\n '@typescript-eslint/dot-notation': 'off',\n // no-ignored-subscription: the canonical pattern in specs is\n // `service.method().subscribe()` used as a fire-trigger for the\n // production code's side effect (typically an HTTP request the spec\n // then asserts via `httpTesting.expectOne`). Jest test isolation\n // makes leaks impossible by construction, so the rule's\n // memory-leak-prevention signal is zero here while the noise is\n // substantial.\n 'rxjs-x/no-ignored-subscription': 'off',\n // component-selector: mocks that substitute Canopy UI library\n // components (`ui-*` selectors owned by `@testgorilla/tgo-ui`)\n // must use the same selectors to slot in correctly under\n // TestBed.overrideComponent.\n '@angular-eslint/component-selector': [\n 'error',\n { type: 'element', prefix: ['tgo', 'ui'], style: 'kebab-case' },\n ],\n // no-non-null-assertion: idiomatic `querySelector('input')!` after\n // an `expect(...).toBeDefined()` or after a static template\n // guarantees the element exists. The spec has already proven\n // non-null upstream; the rule's signal is zero here while the\n // noise is substantial. Same precedent as `dot-notation` /\n // `no-ignored-subscription` — spec-file relaxations match the\n // idiomatic test shape. Production code keeps the rule at error.\n '@typescript-eslint/no-non-null-assertion': 'off',\n // no-underscore-dangle: specs routinely reach into `_`-prefixed\n // internals of services and SignalStore factories to assert\n // against private state (e.g. `(store as unknown as\n // { _resetSubject: ... })._resetSubject()`). The SignalStore\n // factory block already disables this rule for `*.store.ts` /\n // `*.store.feature.ts`, but `*.store.spec.ts` matches the spec\n // block instead — so the disable needs to be here too.\n 'no-underscore-dangle': 'off',\n },\n },\n\n // ── NgRx SignalStore factory files (*.store.ts, *.store.feature.ts) —\n // three rules conflict with the SignalStore authoring pattern:\n // - `explicit-function-return-type`: signalStore() / withFeature()\n // rely on inferred generic return types; naming the type either\n // duplicates inference or narrows below what's intended.\n // - `no-underscore-dangle`: SignalStore convention uses `_`-prefixed\n // internal helpers (e.g. `_state`, `_load`) that don't leak through\n // the public store API.\n // - `prefer-arrow-callback`: factories pass `function` keyword\n // callbacks for proper `this`-binding inside the feature; arrow\n // conversion can change semantics. ──\n {\n files: ['src/**/*.store.ts', 'src/**/*.store.feature.ts'],\n rules: {\n '@typescript-eslint/explicit-function-return-type': 'off',\n 'no-underscore-dangle': 'off',\n 'prefer-arrow-callback': 'off',\n },\n },\n\n // ── JS files ─────────────────────────────────────────────────────────\n {\n files: ['**/*.js'],\n languageOptions: {\n ecmaVersion: 2020,\n sourceType: 'module',\n },\n rules: {\n '@typescript-eslint/no-require-imports': 'off',\n },\n }\n );\n}\n"]}
|