@tsfpp/eslint-config 1.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 ADDED
@@ -0,0 +1,116 @@
1
+ # @tsfpp/eslint-config
2
+
3
+ Shared ESLint flat configuration for [TSF++](../../spec/standards/TSFPP_CODING_STANDARD.md) projects.
4
+
5
+ Enforces the machine-checkable subset of TSF++ rules via `@typescript-eslint` and `eslint-plugin-functional`. Every active rule references the spec rule it enforces.
6
+
7
+ ## Requirements
8
+
9
+ - ESLint ≥ 9 (flat config format)
10
+ - TypeScript ≥ 5.3
11
+ - A `tsconfig.json` reachable from each linted file
12
+
13
+ ## Installation
14
+
15
+ ```sh
16
+ pnpm add -D @tsfpp/eslint-config \
17
+ eslint \
18
+ typescript \
19
+ @typescript-eslint/parser \
20
+ @typescript-eslint/eslint-plugin \
21
+ eslint-plugin-functional
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Standalone
27
+
28
+ ```js
29
+ // eslint.config.js
30
+ import tsfpp from '@tsfpp/eslint-config'
31
+
32
+ export default tsfpp
33
+ ```
34
+
35
+ ### With project-specific overrides
36
+
37
+ ```js
38
+ // eslint.config.js
39
+ import tsfpp from '@tsfpp/eslint-config'
40
+
41
+ export default [
42
+ ...tsfpp,
43
+ {
44
+ // Relax console warnings in scripts
45
+ rules: { 'no-console': 'off' },
46
+ },
47
+ ]
48
+ ```
49
+
50
+ ### With `@tsfpp/tsconfig`
51
+
52
+ ```js
53
+ // eslint.config.js
54
+ import tsfpp from '@tsfpp/eslint-config'
55
+
56
+ export default [
57
+ ...tsfpp,
58
+ {
59
+ languageOptions: {
60
+ parserOptions: {
61
+ // Point to your project tsconfig explicitly if needed
62
+ project: './tsconfig.json',
63
+ },
64
+ },
65
+ },
66
+ ]
67
+ ```
68
+
69
+ ## Enforced rules
70
+
71
+ | ESLint rule | TSF++ rule | Level |
72
+ |-------------|------------|-------|
73
+ | `@typescript-eslint/no-explicit-any` | 1.5 | MUST |
74
+ | `@typescript-eslint/no-non-null-assertion` | 1.6 | MUST |
75
+ | `@typescript-eslint/consistent-type-assertions: never` | 1.6 | MUST |
76
+ | `@typescript-eslint/switch-exhaustiveness-check` | 1.2 / 4.1 | MUST |
77
+ | `@typescript-eslint/explicit-function-return-type` | 3.1 | MUST |
78
+ | `@typescript-eslint/strict-boolean-expressions` | 4.5 | MUST |
79
+ | `@typescript-eslint/no-floating-promises` | 6.4 | SHOULD |
80
+ | `@typescript-eslint/prefer-readonly` | 2.2 | MUST |
81
+ | `functional/no-let` | 2.1 | MUST |
82
+ | `functional/no-loop-statements` | 4.2 | MUST |
83
+ | `functional/no-throw-statements` | 6.2 | MUST |
84
+ | `functional/prefer-readonly-type` | 2.2 | MUST |
85
+ | `functional/immutable-data` | 2.3 | MUST |
86
+ | `functional/no-classes` | 1.9 | MUST |
87
+ | `functional/no-this-expressions` | 1.9 | MUST |
88
+ | `complexity: 10` | 3.4 | MUST |
89
+ | `max-depth: 4` | 3.4 | MUST |
90
+ | `max-lines-per-function: 40` | 3.4 | MUST |
91
+ | `eqeqeq: always` | 4.5 | MUST |
92
+ | `no-param-reassign` | 2.3 | MUST |
93
+
94
+ ## Handling permitted deviations
95
+
96
+ Some TSF++ rules permit deviations at specific boundaries. Use `eslint-disable-next-line` with a paired `DEVIATION` comment so deviations are explicit and auditable:
97
+
98
+ ```typescript
99
+ // DEVIATION(1.6): `as` permitted inside smart constructor boundary
100
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
+ return raw as NodeId
102
+ ```
103
+
104
+ ```typescript
105
+ // DEVIATION(6.2): adapter boundary — wraps third-party throw in Result
106
+ // eslint-disable-next-line functional/no-throw-statements
107
+ throw new Error('unreachable')
108
+ ```
109
+
110
+ This makes every deviation visible to the TSF++ Audit agent and during code review.
111
+
112
+ ## See also
113
+
114
+ - [spec/standards/TSFPP_CODING_STANDARD.md §9](../../spec/standards/TSFPP_CODING_STANDARD.md#9--compiler-and-tooling-configuration) — normative rule reference
115
+ - [spec/rationale/09-tooling.md](../../spec/rationale/09-tooling.md) — extended justification
116
+ - [@tsfpp/tsconfig](../tsconfig/README.md) — companion TypeScript config presets
package/dist/api.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @tsfpp/eslint-config/api
3
+ *
4
+ * TSF++ ESLint configuration profile for HTTP API / Node.js server code.
5
+ * Extends the base config with rules that enforce stricter output hygiene,
6
+ * async correctness, and boundary discipline required by API_CODING_STANDARD.md.
7
+ *
8
+ * Rule references in this file are to API_CODING_STANDARD.md unless prefixed with "TSF++".
9
+ *
10
+ * Usage:
11
+ * // eslint.config.js
12
+ * import tsfppApi from '@tsfpp/eslint-config/api'
13
+ * export default tsfppApi
14
+ *
15
+ * With project-specific overrides:
16
+ * import tsfppApi from '@tsfpp/eslint-config/api'
17
+ * export default [
18
+ * ...tsfppApi,
19
+ * { files: ['src/adapters/**'], rules: { 'no-console': 'off' } },
20
+ * ]
21
+ *
22
+ * No additional devDependencies are required beyond the base package requirements.
23
+ */
24
+ import type { Linter } from 'eslint';
25
+ declare const config: Linter.Config[];
26
+ export default config;
27
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGpC,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EA6D1B,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/api.js ADDED
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @tsfpp/eslint-config/api
3
+ *
4
+ * TSF++ ESLint configuration profile for HTTP API / Node.js server code.
5
+ * Extends the base config with rules that enforce stricter output hygiene,
6
+ * async correctness, and boundary discipline required by API_CODING_STANDARD.md.
7
+ *
8
+ * Rule references in this file are to API_CODING_STANDARD.md unless prefixed with "TSF++".
9
+ *
10
+ * Usage:
11
+ * // eslint.config.js
12
+ * import tsfppApi from '@tsfpp/eslint-config/api'
13
+ * export default tsfppApi
14
+ *
15
+ * With project-specific overrides:
16
+ * import tsfppApi from '@tsfpp/eslint-config/api'
17
+ * export default [
18
+ * ...tsfppApi,
19
+ * { files: ['src/adapters/**'], rules: { 'no-console': 'off' } },
20
+ * ]
21
+ *
22
+ * No additional devDependencies are required beyond the base package requirements.
23
+ */
24
+ import base from './base.js';
25
+ const config = [
26
+ // ── Inherit all base TSF++ rules ─────────────────────────────────────────────
27
+ ...base,
28
+ // ── API-specific overrides and additions ──────────────────────────────────────
29
+ {
30
+ files: ['**/*.ts'],
31
+ rules: {
32
+ // ── Output / logging hygiene ────────────────────────────────────────────
33
+ // API servers must never use console.* — structured logging only (withLogging from logger.ts).
34
+ // The base config sets this to 'warn'; API elevates to 'error'.
35
+ 'no-console': 'error',
36
+ // ── Async correctness (Rules 6.x, TSF++ Rule 6.4) ──────────────────────
37
+ // Every async function must contain at least one await expression.
38
+ // Prevents accidentally marking synchronous handlers as async.
39
+ '@typescript-eslint/require-await': 'error',
40
+ // Returned promises must be awaited (catches fire-and-forget in handlers).
41
+ '@typescript-eslint/return-await': ['error', 'always'],
42
+ // ── Boundary strictness (Rules 1.x, 5.x) ───────────────────────────────
43
+ // API rule 5.1 — every request body / query param must pass through Zod (or equivalent).
44
+ // Enforced structurally; no ESLint rule maps cleanly without custom plugin.
45
+ // Document this at the code-review gate (API_CODING_STANDARD.md §10 checklist).
46
+ // Disallow usage of unsafe any-typed values passed to typed parameters.
47
+ // Belt-and-suspenders at parse/validate boundaries.
48
+ '@typescript-eslint/no-unsafe-argument': 'error',
49
+ '@typescript-eslint/no-unsafe-assignment': 'error',
50
+ '@typescript-eslint/no-unsafe-call': 'error',
51
+ '@typescript-eslint/no-unsafe-member-access': 'error',
52
+ '@typescript-eslint/no-unsafe-return': 'error',
53
+ // ── Error handling (TSF++ Rule 6.2; API Rule 4.x) ──────────────────────
54
+ // functional/no-throw-statements is already 'error' in base.
55
+ // No additional override required; adapter boundaries use DEVIATION(6.2).
56
+ // Prevent Promise rejection with non-Error values.
57
+ 'prefer-promise-reject-errors': 'error',
58
+ },
59
+ },
60
+ // ── Adapter / boundary files — allow `new` and `throw` with deviation ─────────
61
+ // Projects that follow TSF++ boundary conventions will place all I/O adapters in
62
+ // a dedicated directory (e.g. src/adapters/, src/infrastructure/).
63
+ // Override per-project in the consuming eslint.config.js if needed:
64
+ //
65
+ // {
66
+ // files: ['src/adapters/**'],
67
+ // rules: {
68
+ // 'no-restricted-syntax': 'off', // allows `new` and `instanceof`
69
+ // 'functional/no-throw-statements': 'off', // allows `throw` at boundary
70
+ // },
71
+ // },
72
+ ];
73
+ export default config;
74
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,IAAI,MAAiB,WAAW,CAAA;AAEvC,MAAM,MAAM,GAAoB;IAE9B,gFAAgF;IAChF,GAAG,IAAI;IAEP,iFAAiF;IACjF;QACE,KAAK,EAAE,CAAC,SAAS,CAAC;QAClB,KAAK,EAAE;YAEL,2EAA2E;YAE3E,+FAA+F;YAC/F,gEAAgE;YAChE,YAAY,EAAE,OAAO;YAErB,0EAA0E;YAE1E,mEAAmE;YACnE,+DAA+D;YAC/D,kCAAkC,EAAE,OAAO;YAE3C,2EAA2E;YAC3E,iCAAiC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;YAEtD,0EAA0E;YAE1E,yFAAyF;YACzF,4EAA4E;YAC5E,gFAAgF;YAEhF,wEAAwE;YACxE,oDAAoD;YACpD,uCAAuC,EAAI,OAAO;YAClD,yCAAyC,EAAG,OAAO;YACnD,mCAAmC,EAAS,OAAO;YACnD,4CAA4C,EAAE,OAAO;YACrD,qCAAqC,EAAO,OAAO;YAEnD,0EAA0E;YAE1E,6DAA6D;YAC7D,0EAA0E;YAE1E,mDAAmD;YACnD,8BAA8B,EAAE,OAAO;SACxC;KACF;IAED,iFAAiF;IACjF,iFAAiF;IACjF,mEAAmE;IACnE,oEAAoE;IACpE,EAAE;IACF,MAAM;IACN,kCAAkC;IAClC,eAAe;IACf,mFAAmF;IACnF,gFAAgF;IAChF,SAAS;IACT,OAAO;CACR,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/base.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @tsfpp/eslint-config — base
3
+ *
4
+ * Shared ESLint flat configuration for TSF++ projects (pure TypeScript targets).
5
+ * Enforces Rules 1.2–1.9, 2.1–2.3, 3.1–3.2, 3.4, 4.1, 4.2, 4.5, 6.2, 6.4, 11.2
6
+ * from CODING_STANDARD.md via @typescript-eslint and eslint-plugin-functional.
7
+ *
8
+ * Usage (base only):
9
+ * // eslint.config.js
10
+ * import tsfpp from '@tsfpp/eslint-config'
11
+ * export default tsfpp
12
+ *
13
+ * Usage with project-specific overrides:
14
+ * import tsfpp from '@tsfpp/eslint-config'
15
+ * export default [
16
+ * ...tsfpp,
17
+ * { rules: { 'no-console': 'off' } },
18
+ * ]
19
+ *
20
+ * For React projects, import '@tsfpp/eslint-config/react' instead.
21
+ * For API projects, import '@tsfpp/eslint-config/api' instead.
22
+ */
23
+ import type { Linter } from 'eslint';
24
+ declare const config: Linter.Config[];
25
+ export default config;
26
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAO,QAAQ,CAAA;AAMrC,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EA0L1B,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/base.js ADDED
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @tsfpp/eslint-config — base
3
+ *
4
+ * Shared ESLint flat configuration for TSF++ projects (pure TypeScript targets).
5
+ * Enforces Rules 1.2–1.9, 2.1–2.3, 3.1–3.2, 3.4, 4.1, 4.2, 4.5, 6.2, 6.4, 11.2
6
+ * from CODING_STANDARD.md via @typescript-eslint and eslint-plugin-functional.
7
+ *
8
+ * Usage (base only):
9
+ * // eslint.config.js
10
+ * import tsfpp from '@tsfpp/eslint-config'
11
+ * export default tsfpp
12
+ *
13
+ * Usage with project-specific overrides:
14
+ * import tsfpp from '@tsfpp/eslint-config'
15
+ * export default [
16
+ * ...tsfpp,
17
+ * { rules: { 'no-console': 'off' } },
18
+ * ]
19
+ *
20
+ * For React projects, import '@tsfpp/eslint-config/react' instead.
21
+ * For API projects, import '@tsfpp/eslint-config/api' instead.
22
+ */
23
+ import tsParser from '@typescript-eslint/parser';
24
+ import tsPlugin from '@typescript-eslint/eslint-plugin';
25
+ import functionalPlugin from 'eslint-plugin-functional';
26
+ import { coercePlugin } from './plugin-compat.js';
27
+ const config = [
28
+ // ── Global ignores ────────────────────────────────────────────────────────────
29
+ {
30
+ ignores: ['dist/**', 'coverage/**', 'node_modules/**', '**/*.d.ts'],
31
+ },
32
+ // ── TypeScript source files ───────────────────────────────────────────────────
33
+ {
34
+ files: ['**/*.ts', '**/*.tsx'],
35
+ languageOptions: {
36
+ parser: tsParser,
37
+ parserOptions: {
38
+ sourceType: 'module',
39
+ ecmaVersion: 'latest',
40
+ project: true, // resolves nearest tsconfig.json; override with projectService
41
+ },
42
+ },
43
+ plugins: {
44
+ '@typescript-eslint': coercePlugin(tsPlugin),
45
+ 'functional': coercePlugin(functionalPlugin),
46
+ },
47
+ rules: {
48
+ // ── Type-system rules ─────────────────────────────────────────────────────
49
+ // Rule 1.2 / 4.1 — exhaustive switch via never (backed by @tsfpp/prelude absurd)
50
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
51
+ // Rule 1.4 — prefer `type` over `interface`; `interface` requires DEVIATION(1.4)
52
+ '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
53
+ // Rule 1.5 — no `any`
54
+ '@typescript-eslint/no-explicit-any': 'error',
55
+ // Rule 1.6 — no `!`
56
+ '@typescript-eslint/no-non-null-assertion': 'error',
57
+ // Rule 1.6 — no `as` (DEVIATION(1.6) + eslint-disable required inside smart constructors)
58
+ '@typescript-eslint/consistent-type-assertions': ['error', {
59
+ assertionStyle: 'never',
60
+ }],
61
+ // Rule 1.8 / 1.9 — forbidden language constructs (no ESLint plugin covers these directly)
62
+ 'no-restricted-syntax': [
63
+ 'error',
64
+ {
65
+ // Rule 1.8 — no enum
66
+ selector: 'TSEnumDeclaration',
67
+ message: 'TSF++ Rule 1.8: Use string literal unions or `as const` objects instead of enum.',
68
+ },
69
+ {
70
+ // Rule 1.9 — no namespace
71
+ selector: "TSModuleDeclaration[kind='namespace']",
72
+ message: 'TSF++ Rule 1.9: Namespace declarations are forbidden.',
73
+ },
74
+ {
75
+ // Rule 1.9 — no instanceof (prefer discriminated unions and type-guard predicates)
76
+ selector: 'BinaryExpression[operator="instanceof"]',
77
+ message: 'TSF++ Rule 1.9: instanceof is forbidden; use discriminated unions or exported type-guard predicates.',
78
+ },
79
+ {
80
+ // Rule 1.9 — no new (adapter boundaries require DEVIATION(1.9) comment + eslint-disable)
81
+ selector: 'NewExpression',
82
+ message: 'TSF++ Rule 1.9: new is forbidden outside adapter boundaries. Add DEVIATION(1.9) and an eslint-disable comment.',
83
+ },
84
+ ],
85
+ // ── Immutability & functional style ──────────────────────────────────────
86
+ // Rule 2.1 — no `let`
87
+ 'functional/no-let': 'error',
88
+ // Rule 2.2 — readonly types (deep)
89
+ 'functional/prefer-readonly-type': ['error', {
90
+ allowLocalMutation: false,
91
+ allowMutableReturnType: false,
92
+ ignoreClass: false,
93
+ ignoreInterface: false,
94
+ }],
95
+ // Rule 2.2 — prefer-readonly on (legacy) class properties (belt-and-suspenders)
96
+ '@typescript-eslint/prefer-readonly': 'error',
97
+ // Rule 2.3 — no mutation (property assignment, array mutation methods)
98
+ 'functional/immutable-data': ['error', {
99
+ ignoreImmediateMutation: true, // allows builder pattern inside same statement
100
+ ignoreAccessorPattern: ['**.current', 'process.env.*'], // React refs + env edge cases
101
+ }],
102
+ // Rule 1.9 — no classes / no this
103
+ 'functional/no-classes': 'error',
104
+ 'functional/no-this-expressions': 'error',
105
+ // Rule 4.2 — no imperative loops
106
+ 'functional/no-loop-statements': 'error',
107
+ // Rule 6.2 — no throw outside adapter boundaries
108
+ // Disable per-file with `// eslint-disable-next-line functional/no-throw-statements`
109
+ // accompanied by a `// DEVIATION(6.2)` comment at every adapter entry point.
110
+ 'functional/no-throw-statements': 'error',
111
+ // ── Function rules ────────────────────────────────────────────────────────
112
+ // Rule 3.1 — explicit return type on every exported function
113
+ '@typescript-eslint/explicit-function-return-type': ['error', {
114
+ allowExpressions: false,
115
+ allowTypedFunctionExpressions: true,
116
+ allowHigherOrderFunctions: true,
117
+ allowDirectConstAssertionInArrowFunctions: true,
118
+ }],
119
+ // Rule 3.2 — arity ≤ 3; use a readonly record for ≥ 3 parameters
120
+ 'max-params': ['error', { max: 3 }],
121
+ // Rule 3.4 — cyclomatic complexity ≤ 10
122
+ 'complexity': ['error', { max: 10 }],
123
+ // Rule 3.4 — nesting depth ≤ 4
124
+ 'max-depth': ['error', { max: 4 }],
125
+ // Rule 3.4 — 40-line function body limit
126
+ 'max-lines-per-function': ['error', {
127
+ max: 40,
128
+ skipBlankLines: true,
129
+ skipComments: true,
130
+ }],
131
+ // ── Async / promise safety ────────────────────────────────────────────────
132
+ // Rule 6.4 — no unhandled promise rejections
133
+ '@typescript-eslint/no-floating-promises': 'error',
134
+ '@typescript-eslint/no-misused-promises': 'error',
135
+ // ── Control-flow hygiene ──────────────────────────────────────────────────
136
+ // Rule 4.5 — no truthiness checks on non-booleans
137
+ '@typescript-eslint/strict-boolean-expressions': ['error', {
138
+ allowString: false,
139
+ allowNumber: false,
140
+ allowNullableObject: false,
141
+ allowNullableBoolean: false,
142
+ allowNullableString: false,
143
+ allowNullableNumber: false,
144
+ allowAny: false,
145
+ }],
146
+ // ── Module hygiene ────────────────────────────────────────────────────────
147
+ // Prefer `import type` for type-only imports (verbatimModuleSyntax companion)
148
+ '@typescript-eslint/consistent-type-imports': ['error', {
149
+ prefer: 'type-imports',
150
+ fixStyle: 'inline-type-imports',
151
+ disallowTypeAnnotations: false,
152
+ }],
153
+ // ── General hygiene ───────────────────────────────────────────────────────
154
+ // Accidental console.log in production code — warn in base; API profile overrides to error
155
+ 'no-console': 'warn',
156
+ // Rule 2.1 — const only
157
+ 'prefer-const': 'error',
158
+ 'no-var': 'error',
159
+ // Rule 2.3 — no parameter reassignment
160
+ 'no-param-reassign': 'error',
161
+ // Rule 4.5 — strict equality
162
+ 'eqeqeq': ['error', 'always'],
163
+ // Rule 11.2 — file length ≤ 400 lines (800 absolute maximum via DEVIATION(11.2))
164
+ 'max-lines': ['error', {
165
+ max: 400,
166
+ skipBlankLines: true,
167
+ skipComments: true,
168
+ }],
169
+ // Unused vars — `_` prefix exempted (Rule 7.6)
170
+ '@typescript-eslint/no-unused-vars': ['error', {
171
+ argsIgnorePattern: '^_',
172
+ varsIgnorePattern: '^_',
173
+ caughtErrorsIgnorePattern: '^_',
174
+ }],
175
+ },
176
+ },
177
+ ];
178
+ export default config;
179
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * plugin-compat.ts
3
+ *
4
+ * Adapter boundary for third-party ESLint plugin type coercion.
5
+ *
6
+ * Problem: ESLint plugin packages frequently ship TypeScript types that lag
7
+ * behind the current @eslint/core `Plugin` interface. The structural mismatch
8
+ * (e.g. `null` in `parser` where `string | undefined` is expected, or `flat`
9
+ * keys in `configs` that don't satisfy the index signature) causes TS2322
10
+ * errors at plugin registration sites in flat config objects.
11
+ *
12
+ * Solution: Isolate the necessary `as` cast here, at this single adapter
13
+ * boundary. Every callsite in base.ts / react.ts / api.ts is auditable by
14
+ * grepping for `coercePlugin`.
15
+ *
16
+ * DEVIATION(1.6): `as` cast is intentional and confined to this module.
17
+ * Justification: third-party type incompatibility at an adapter boundary;
18
+ * no runtime effect — this is a pure type-level coercion with zero behavior.
19
+ * Reviewed and approved per TSF++ deviation procedure.
20
+ */
21
+ import type { ESLint } from 'eslint';
22
+ /**
23
+ * Coerces a third-party ESLint plugin object to the canonical `ESLint.Plugin`
24
+ * type accepted by flat config `plugins` records.
25
+ *
26
+ * Use exclusively at plugin registration sites. Never use to silence unrelated
27
+ * type errors.
28
+ */
29
+ export declare const coercePlugin: (plugin: unknown) => ESLint.Plugin;
30
+ //# sourceMappingURL=plugin-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-compat.d.ts","sourceRoot":"","sources":["../plugin-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEpC;;;;;;GAMG;AAEH,eAAO,MAAM,YAAY,GAAI,QAAQ,OAAO,KAAG,MAAM,CAAC,MAC7B,CAAA"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * plugin-compat.ts
3
+ *
4
+ * Adapter boundary for third-party ESLint plugin type coercion.
5
+ *
6
+ * Problem: ESLint plugin packages frequently ship TypeScript types that lag
7
+ * behind the current @eslint/core `Plugin` interface. The structural mismatch
8
+ * (e.g. `null` in `parser` where `string | undefined` is expected, or `flat`
9
+ * keys in `configs` that don't satisfy the index signature) causes TS2322
10
+ * errors at plugin registration sites in flat config objects.
11
+ *
12
+ * Solution: Isolate the necessary `as` cast here, at this single adapter
13
+ * boundary. Every callsite in base.ts / react.ts / api.ts is auditable by
14
+ * grepping for `coercePlugin`.
15
+ *
16
+ * DEVIATION(1.6): `as` cast is intentional and confined to this module.
17
+ * Justification: third-party type incompatibility at an adapter boundary;
18
+ * no runtime effect — this is a pure type-level coercion with zero behavior.
19
+ * Reviewed and approved per TSF++ deviation procedure.
20
+ */
21
+ /**
22
+ * Coerces a third-party ESLint plugin object to the canonical `ESLint.Plugin`
23
+ * type accepted by flat config `plugins` records.
24
+ *
25
+ * Use exclusively at plugin registration sites. Never use to silence unrelated
26
+ * type errors.
27
+ */
28
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
29
+ export const coercePlugin = (plugin) => plugin; // DEVIATION(1.6): see module JSDoc above
30
+ //# sourceMappingURL=plugin-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-compat.js","sourceRoot":"","sources":["../plugin-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;;;;;;GAMG;AACH,yEAAyE;AACzE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAe,EAAiB,EAAE,CAC7D,MAAuB,CAAA,CAAE,yCAAyC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @tsfpp/eslint-config/react
3
+ *
4
+ * TSF++ ESLint configuration profile for React / TSX code.
5
+ * Extends the base config with React-, hooks-, accessibility-, and TanStack Query–specific rules.
6
+ *
7
+ * Enforces rules from REACT_CODING_STANDARD.md (a profile of CODING_STANDARD.md).
8
+ * Rule references in this file are to REACT_CODING_STANDARD.md unless prefixed with "TSF++".
9
+ *
10
+ * Usage:
11
+ * // eslint.config.js
12
+ * import tsfppReact from '@tsfpp/eslint-config/react'
13
+ * export default tsfppReact
14
+ *
15
+ * With project-specific overrides:
16
+ * import tsfppReact from '@tsfpp/eslint-config/react'
17
+ * export default [
18
+ * ...tsfppReact,
19
+ * { rules: { 'react/display-name': 'off' } },
20
+ * ]
21
+ *
22
+ * Required devDependencies (in addition to base requirements):
23
+ * eslint-plugin-react
24
+ * eslint-plugin-react-hooks
25
+ * eslint-plugin-jsx-a11y
26
+ * @tanstack/eslint-plugin-query
27
+ */
28
+ import type { Linter } from 'eslint';
29
+ declare const config: Linter.Config[];
30
+ export default config;
31
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAS,QAAQ,CAAA;AASvC,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAqG1B,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/react.js ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @tsfpp/eslint-config/react
3
+ *
4
+ * TSF++ ESLint configuration profile for React / TSX code.
5
+ * Extends the base config with React-, hooks-, accessibility-, and TanStack Query–specific rules.
6
+ *
7
+ * Enforces rules from REACT_CODING_STANDARD.md (a profile of CODING_STANDARD.md).
8
+ * Rule references in this file are to REACT_CODING_STANDARD.md unless prefixed with "TSF++".
9
+ *
10
+ * Usage:
11
+ * // eslint.config.js
12
+ * import tsfppReact from '@tsfpp/eslint-config/react'
13
+ * export default tsfppReact
14
+ *
15
+ * With project-specific overrides:
16
+ * import tsfppReact from '@tsfpp/eslint-config/react'
17
+ * export default [
18
+ * ...tsfppReact,
19
+ * { rules: { 'react/display-name': 'off' } },
20
+ * ]
21
+ *
22
+ * Required devDependencies (in addition to base requirements):
23
+ * eslint-plugin-react
24
+ * eslint-plugin-react-hooks
25
+ * eslint-plugin-jsx-a11y
26
+ * @tanstack/eslint-plugin-query
27
+ */
28
+ import reactPlugin from 'eslint-plugin-react';
29
+ import reactHooksPlugin from 'eslint-plugin-react-hooks';
30
+ // eslint-plugin-jsx-a11y ships no types — declared in declarations.d.ts
31
+ import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
32
+ import tanstackQueryPlugin from '@tanstack/eslint-plugin-query';
33
+ import base from './base.js';
34
+ import { coercePlugin } from './plugin-compat.js';
35
+ const config = [
36
+ // ── Inherit all base TSF++ rules (applies to .ts and .tsx) ───────────────────
37
+ ...base,
38
+ // ── React / TSX layer ────────────────────────────────────────────────────────
39
+ {
40
+ files: ['**/*.tsx'],
41
+ plugins: {
42
+ 'react': coercePlugin(reactPlugin),
43
+ 'react-hooks': coercePlugin(reactHooksPlugin),
44
+ 'jsx-a11y': coercePlugin(jsxA11yPlugin),
45
+ '@tanstack/query': coercePlugin(tanstackQueryPlugin),
46
+ },
47
+ settings: {
48
+ react: { version: 'detect' },
49
+ },
50
+ rules: {
51
+ // ── Component shape (Rules 1.1–1.2) ────────────────────────────────────
52
+ // Rule 1.1 — no function declarations for components (must be arrow const)
53
+ // `@typescript-eslint/explicit-function-return-type` already enforces the return type half;
54
+ // this prevents the function-declaration form.
55
+ 'react/function-component-definition': ['error', {
56
+ namedComponents: 'arrow-function',
57
+ unnamedComponents: 'arrow-function',
58
+ }],
59
+ // JSX transform — no explicit React import required (React 17+)
60
+ 'react/jsx-uses-react': 'off',
61
+ 'react/react-in-jsx-scope': 'off',
62
+ // Rule core — JSX hygiene
63
+ 'react/jsx-key': ['error', { checkFragmentShorthand: true }],
64
+ 'react/jsx-no-leaked-render': 'error', // forbids `{count && <X />}` rendering "0"
65
+ 'react/no-array-index-key': 'error', // index keys break diffing
66
+ 'react/no-unstable-nested-components': 'error', // new component identity per render
67
+ 'react/self-closing-comp': 'error',
68
+ 'react/jsx-pascal-case': 'error',
69
+ 'react/jsx-no-useless-fragment': 'error',
70
+ 'react/display-name': 'error',
71
+ // ── Hooks (Rules 4.1–4.6, 14.1) ────────────────────────────────────────
72
+ // Rule 14.1 — hooks rules (conditional calls, top-level only)
73
+ 'react-hooks/rules-of-hooks': 'error',
74
+ // Rule 4.6 — exhaustive deps (disabling this rule requires DEVIATION(4.6))
75
+ 'react-hooks/exhaustive-deps': 'error',
76
+ // ── Props (Rules 2.1–2.4) ───────────────────────────────────────────────
77
+ // Rule 2.4 — no unrestricted rest-prop spread onto DOM elements
78
+ // Note: enforced structurally by Rule 2.1 (explicit Props types); no ESLint rule maps
79
+ // cleanly here without excessive false positives. Code review is the gate.
80
+ // ── Accessibility (Rule 16) ─────────────────────────────────────────────
81
+ // Rule 16.1 — no div/span with onClick; use semantic elements
82
+ 'jsx-a11y/click-events-have-key-events': 'error',
83
+ 'jsx-a11y/no-static-element-interactions': 'error',
84
+ // Rule 16.2 — accessible forms and images
85
+ 'jsx-a11y/alt-text': 'error',
86
+ 'jsx-a11y/anchor-has-content': 'error',
87
+ 'jsx-a11y/label-has-associated-control': 'error',
88
+ // Rule 16 — ARIA correctness
89
+ 'jsx-a11y/aria-props': 'error',
90
+ 'jsx-a11y/aria-role': 'error',
91
+ // Autofocus is harmful to keyboard navigation (warn to allow deliberate UX decisions)
92
+ 'jsx-a11y/no-autofocus': 'warn',
93
+ // ── TanStack Query (Rules 7.1–7.2) ─────────────────────────────────────
94
+ // Rule 7.2 — exhaustive query-key dependencies
95
+ '@tanstack/query/exhaustive-deps': 'error',
96
+ // Discourage rest-destructuring of query results (encourages explicit field selection)
97
+ '@tanstack/query/no-rest-destructuring': 'error',
98
+ // Stable query-client reference (no inline `new QueryClient()` in render)
99
+ '@tanstack/query/stable-query-client': 'error',
100
+ // ── React-specific functional overrides ─────────────────────────────────
101
+ // React refs are mutable by contract; immutable-data would false-positive on ref.current
102
+ // The base config already allowlists `**.current` via ignoreAccessorPattern — no override needed.
103
+ },
104
+ },
105
+ // ── React hooks in plain .ts files (custom hooks outside .tsx) ───────────────
106
+ {
107
+ files: ['**/use*.ts', '**/use*.tsx'],
108
+ rules: {
109
+ 'react-hooks/rules-of-hooks': 'error',
110
+ 'react-hooks/exhaustive-deps': 'error',
111
+ },
112
+ },
113
+ ];
114
+ export default config;
115
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,WAAW,MAAa,qBAAqB,CAAA;AACpD,OAAO,gBAAgB,MAAQ,2BAA2B,CAAA;AAC1D,wEAAwE;AACxE,OAAO,aAAa,MAAW,wBAAwB,CAAA;AACvD,OAAO,mBAAmB,MAAM,+BAA+B,CAAA;AAC/D,OAAO,IAAI,MAAoB,WAAW,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAQ,oBAAoB,CAAA;AAEnD,MAAM,MAAM,GAAoB;IAE9B,gFAAgF;IAChF,GAAG,IAAI;IAEP,gFAAgF;IAChF;QACE,KAAK,EAAE,CAAC,UAAU,CAAC;QACnB,OAAO,EAAE;YACP,OAAO,EAAc,YAAY,CAAC,WAAW,CAAC;YAC9C,aAAa,EAAQ,YAAY,CAAC,gBAAgB,CAAC;YACnD,UAAU,EAAW,YAAY,CAAC,aAAa,CAAC;YAChD,iBAAiB,EAAI,YAAY,CAAC,mBAAmB,CAAC;SACvD;QACD,QAAQ,EAAE;YACR,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;SAC7B;QACD,KAAK,EAAE;YAEL,0EAA0E;YAE1E,2EAA2E;YAC3E,4FAA4F;YAC5F,+CAA+C;YAC/C,qCAAqC,EAAE,CAAC,OAAO,EAAE;oBAC/C,eAAe,EAAK,gBAAgB;oBACpC,iBAAiB,EAAG,gBAAgB;iBACrC,CAAC;YAEF,gEAAgE;YAChE,sBAAsB,EAAO,KAAK;YAClC,0BAA0B,EAAG,KAAK;YAElC,0BAA0B;YAC1B,eAAe,EAAqB,CAAC,OAAO,EAAE,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC;YAC/E,4BAA4B,EAAQ,OAAO,EAAI,2CAA2C;YAC1F,0BAA0B,EAAU,OAAO,EAAI,2BAA2B;YAC1E,qCAAqC,EAAE,OAAO,EAAE,oCAAoC;YACpF,yBAAyB,EAAW,OAAO;YAC3C,uBAAuB,EAAa,OAAO;YAC3C,+BAA+B,EAAK,OAAO;YAC3C,oBAAoB,EAAgB,OAAO;YAE3C,0EAA0E;YAE1E,8DAA8D;YAC9D,4BAA4B,EAAI,OAAO;YAEvC,2EAA2E;YAC3E,6BAA6B,EAAG,OAAO;YAEvC,2EAA2E;YAE3E,gEAAgE;YAChE,sFAAsF;YACtF,2EAA2E;YAE3E,2EAA2E;YAE3E,8DAA8D;YAC9D,uCAAuC,EAAG,OAAO;YACjD,yCAAyC,EAAE,OAAO;YAElD,0CAA0C;YAC1C,mBAAmB,EAAoB,OAAO;YAC9C,6BAA6B,EAAU,OAAO;YAC9C,uCAAuC,EAAE,OAAO;YAEhD,6BAA6B;YAC7B,qBAAqB,EAAG,OAAO;YAC/B,oBAAoB,EAAI,OAAO;YAE/B,sFAAsF;YACtF,uBAAuB,EAAE,MAAM;YAE/B,0EAA0E;YAE1E,+CAA+C;YAC/C,iCAAiC,EAAK,OAAO;YAE7C,uFAAuF;YACvF,uCAAuC,EAAE,OAAO;YAEhD,0EAA0E;YAC1E,qCAAqC,EAAE,OAAO;YAE9C,2EAA2E;YAE3E,yFAAyF;YACzF,kGAAkG;SACnG;KACF;IAED,gFAAgF;IAChF;QACE,KAAK,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC;QACpC,KAAK,EAAE;YACL,4BAA4B,EAAG,OAAO;YACtC,6BAA6B,EAAE,OAAO;SACvC;KACF;CACF,CAAA;AAED,eAAe,MAAM,CAAA"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@tsfpp/eslint-config",
3
+ "version": "1.0.0",
4
+ "description": "Shared ESLint flat configuration for TSF++ projects",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslint-config",
8
+ "typescript",
9
+ "tsfpp",
10
+ "functional",
11
+ "immutability"
12
+ ],
13
+ "homepage": "https://github.com/tsfpp/tsfpp#readme",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/tsfpp/tsfpp.git",
17
+ "directory": "packages/eslint-config"
18
+ },
19
+ "license": "MIT",
20
+ "type": "module",
21
+ "exports": {
22
+ ".": "./dist/base.js",
23
+ "./react": "./dist/react.js",
24
+ "./api": "./dist/api.js",
25
+ "./package.json": "./package.json"
26
+ },
27
+ "files": [
28
+ "dist/",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsc --project tsconfig.build.json",
33
+ "prepublishOnly": "pnpm run build",
34
+ "lint": "eslint dist/",
35
+ "test": "node --input-type=module --eval \"import './dist/base.js'\""
36
+ },
37
+ "engines": {
38
+ "node": ">=18.18.0"
39
+ },
40
+ "peerDependencies": {
41
+ "@tanstack/eslint-plugin-query": ">=5.0.0",
42
+ "@typescript-eslint/eslint-plugin": ">=8.0.0",
43
+ "@typescript-eslint/parser": ">=8.0.0",
44
+ "eslint": ">=9.0.0",
45
+ "eslint-plugin-functional": "^9.0.0",
46
+ "eslint-plugin-jsx-a11y": ">=6.0.0",
47
+ "eslint-plugin-react": ">=7.0.0",
48
+ "eslint-plugin-react-hooks": ">=5.0.0",
49
+ "typescript": ">=5.3.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@tanstack/eslint-plugin-query": { "optional": true },
53
+ "eslint-plugin-jsx-a11y": { "optional": true },
54
+ "eslint-plugin-react": { "optional": true },
55
+ "eslint-plugin-react-hooks": { "optional": true }
56
+ },
57
+ "devDependencies": {
58
+ "@tanstack/eslint-plugin-query": "^5.100.10",
59
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
60
+ "@typescript-eslint/parser": "^8.59.3",
61
+ "eslint": "^9.39.4",
62
+ "eslint-plugin-functional": "^9.0.0",
63
+ "eslint-plugin-jsx-a11y": "^6.10.2",
64
+ "eslint-plugin-react": "^7.37.5",
65
+ "eslint-plugin-react-hooks": "^7.1.1",
66
+ "typescript": "^5.9.3"
67
+ }
68
+ }