@antelopejs/tooling-configs 0.0.8 → 0.2.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 +149 -130
- package/dist/bin/check-interface-ranges.mjs +10 -1
- package/dist/bin/check-size.d.mts +1 -0
- package/dist/bin/check-size.mjs +51 -0
- package/dist/bin/checks.d.mts +1 -0
- package/dist/bin/checks.mjs +51 -0
- package/dist/bin/ratchet.d.mts +1 -0
- package/dist/bin/ratchet.mjs +66 -0
- package/dist/bin/sync.d.mts +1 -0
- package/dist/bin/sync.mjs +485 -0
- package/dist/ceilings--pJmhSde.mjs +64 -0
- package/dist/eslint.mjs +24 -4
- package/dist/files-BSl0U8lT.mjs +98 -0
- package/dist/knip.mjs +5 -0
- package/dist/oxc/fmt.mjs +1 -1
- package/dist/oxc/guardrails/index.d.mts +6 -0
- package/dist/oxc/guardrails/index.mjs +318 -0
- package/dist/oxc/lint.d.mts +128 -151
- package/dist/oxc/lint.mjs +100 -125
- package/dist/package-B1aipTbn.mjs +115 -0
- package/dist/ratchet-DNsVZH9s.mjs +172 -0
- package/dist/shared-BG0Nkzh0.d.mts +8 -0
- package/dist/{shared-Ch-ZcMQb.mjs → shared-NC0T8ykm.mjs} +5 -1
- package/dist/shared-WC0z3y9F.mjs +63 -0
- package/dist/size-DRCgYCLA.mjs +17 -0
- package/package.json +29 -7
package/dist/oxc/lint.d.mts
CHANGED
|
@@ -1,160 +1,92 @@
|
|
|
1
|
+
import { n as TEST_FILE_GLOBS, t as ASSERTION_FUNCTION_NAMES } from "../shared-BG0Nkzh0.mjs";
|
|
1
2
|
//#region src/oxc/lint.d.ts
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* them when a repository adds patterns of its own.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* export default defineConfig({
|
|
10
|
-
* extends: [antelopePreset()],
|
|
11
|
-
* ignorePatterns: [...ANTELOPE_IGNORE_PATTERNS, "playground/**"],
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
4
|
+
* oxlint replaces rather than merges ignorePatterns across extends.
|
|
5
|
+
* Spread these patterns when adding repository-specific ignores.
|
|
14
6
|
*/
|
|
15
7
|
declare const ANTELOPE_IGNORE_PATTERNS: string[];
|
|
16
|
-
type Severity = "off" | "
|
|
17
|
-
/**
|
|
18
|
-
* Thresholds for the complexity rules. The defaults are deliberately looser than
|
|
19
|
-
* oxlint's own (3 parameters, 50 lines per function): AntelopeJS handlers take a
|
|
20
|
-
* request context plus its dependencies, and interface files declare long types.
|
|
21
|
-
* They are meant to catch the outliers, not to redesign every signature.
|
|
22
|
-
*/
|
|
8
|
+
type Severity = "off" | "error";
|
|
9
|
+
/** Thresholds allow request contexts and dependencies while rejecting outlier signatures and files. */
|
|
23
10
|
interface ComplexityThresholds {
|
|
24
|
-
/** `eslint/max-params` (oxlint default: 3). */
|
|
25
11
|
maxParams: number;
|
|
26
|
-
/** `eslint/max-lines-per-function` (oxlint default: 50). */
|
|
27
12
|
maxLinesPerFunction: number;
|
|
28
|
-
/** `eslint/max-lines` (oxlint default: 300). */
|
|
29
13
|
maxLines: number;
|
|
30
|
-
/** `eslint/max-depth` (oxlint default: 4). */
|
|
31
14
|
maxDepth: number;
|
|
32
|
-
/** `eslint/complexity`, cyclomatic (oxlint default: 20). */
|
|
33
15
|
complexity: number;
|
|
34
16
|
}
|
|
35
17
|
declare const DEFAULT_COMPLEXITY_THRESHOLDS: ComplexityThresholds;
|
|
36
18
|
interface AntelopePresetOptions {
|
|
19
|
+
/** All fifteen vendored anti-slop rules. Defaults to true. */
|
|
20
|
+
antiSlop?: boolean;
|
|
21
|
+
/** Comment and test-quality rules. Defaults to true. */
|
|
22
|
+
guardrails?: boolean;
|
|
23
|
+
/** Complexity limits at error. Pass an object to override thresholds, or false to disable. */
|
|
24
|
+
complexity?: boolean | Partial<ComplexityThresholds>;
|
|
37
25
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
antiSlop?: boolean | Severity;
|
|
46
|
-
/**
|
|
47
|
-
* Complexity ceilings. Pass an object to override individual thresholds.
|
|
48
|
-
*
|
|
49
|
-
* @default "warn" with {@link DEFAULT_COMPLEXITY_THRESHOLDS}
|
|
50
|
-
*/
|
|
51
|
-
complexity?: boolean | (Partial<ComplexityThresholds> & {
|
|
52
|
-
severity?: Severity;
|
|
53
|
-
});
|
|
54
|
-
/**
|
|
55
|
-
* Import sorting through `eslint-plugin-perfectionist`, autofixed by
|
|
56
|
-
* `oxlint --fix`.
|
|
57
|
-
*
|
|
58
|
-
* Off by default, because the sort moves value imports across side-effect
|
|
59
|
-
* imports and module evaluation order is load-bearing in an AntelopeJS
|
|
60
|
-
* module: `import "./components"` is what puts the decorated classes in the
|
|
61
|
-
* registry. Running it over the cms/dms repositories moved
|
|
62
|
-
* `import { CORE_SCHEMA_NAME } from ".../constants"` from before
|
|
63
|
-
* `import "./db"` to after `import "./routes"` -- in a file whose comment
|
|
64
|
-
* says the position is deliberate -- and broke the package at require time.
|
|
65
|
-
* Nothing in a typecheck or a build catches it.
|
|
66
|
-
*
|
|
67
|
-
* `sortSideEffects: false` is not enough: it keeps side-effect imports in
|
|
68
|
-
* place (verified across 1402 files, none moved) but lets everything else
|
|
69
|
-
* cross them. `partitionByNewLine`, which would fix that, is refused by
|
|
70
|
-
* perfectionist 5.11 -- it conflicts with both `newlinesBetween` and
|
|
71
|
-
* `newlinesInside`. Turn this back on when the rule can guarantee that no
|
|
72
|
-
* import crosses a side-effect import.
|
|
73
|
-
*
|
|
74
|
-
* The plugin is an optional peer dependency: it pulls ESLint and
|
|
75
|
-
* typescript-eslint in with it, which a repository leaving this off has no
|
|
76
|
-
* reason to install. Add `eslint-plugin-perfectionist` alongside this package
|
|
77
|
-
* when turning it on.
|
|
78
|
-
*
|
|
79
|
-
* @default false
|
|
26
|
+
* Import sorting through eslint-plugin-perfectionist, autofixed by oxlint --fix.
|
|
27
|
+
* Off by default because sorting value imports across side-effect imports
|
|
28
|
+
* changes module registration order and breaks AntelopeJS packages at require time.
|
|
29
|
+
* sortSideEffects: false keeps side-effect imports in place but lets values cross them.
|
|
30
|
+
* perfectionist 5.11 refuses partitionByNewLine with newlinesBetween or newlinesInside.
|
|
31
|
+
* Enable only when no import can cross a side-effect import, and install the optional
|
|
32
|
+
* eslint-plugin-perfectionist peer dependency alongside this package.
|
|
80
33
|
*/
|
|
81
34
|
importSorting?: boolean;
|
|
35
|
+
/** Import cycles fail at runtime. Defaults to true. */
|
|
36
|
+
importCycles?: boolean;
|
|
82
37
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* has cycles needs to see them without a red pipeline while it untangles them.
|
|
86
|
-
*
|
|
87
|
-
* @default "error"
|
|
88
|
-
*/
|
|
89
|
-
importCycles?: boolean | Severity;
|
|
90
|
-
/**
|
|
91
|
-
* `typescript/no-floating-promises`, which needs type information. The
|
|
92
|
-
* consuming repository must also set `options.typeAware` in its own root
|
|
93
|
-
* config: oxlint only reads that field there, never from an extended preset.
|
|
94
|
-
*
|
|
95
|
-
* @default true
|
|
38
|
+
* Type-aware rules. Defaults to true. Consumers must also set options.typeAware
|
|
39
|
+
* in their root config because oxlint never reads that field from extends.
|
|
96
40
|
*/
|
|
97
41
|
typeAware?: boolean;
|
|
98
42
|
}
|
|
99
|
-
/** Every
|
|
100
|
-
/**
|
|
101
|
-
* The anti-slop rules left off by default.
|
|
102
|
-
*
|
|
103
|
-
* Measured across the sixteen cms/dms repositories: these seven produced 3038
|
|
104
|
-
* of the 3429 anti-slop findings, and every sample we read was either the
|
|
105
|
-
* correct idiom or a design change well beyond a lint pass.
|
|
106
|
-
*
|
|
107
|
-
* - `require-safety-comment-for-type-assertion` (1283) is satisfied by writing
|
|
108
|
-
* a comment, so at that volume it manufactures the noise it exists to fight.
|
|
109
|
-
* Removing assertions is the goal; annotating them is not.
|
|
110
|
-
* - `no-unknown-parameters` (566) and `no-unknown-returns` (104) fire on catch
|
|
111
|
-
* handlers, where `unknown` is the only correct type, and on the parsers
|
|
112
|
-
* whose whole job is to take unknown in and hand typed values out.
|
|
113
|
-
* - `no-runtime-typeof` (460) assumes a validation layer above the check. In a
|
|
114
|
-
* CMS reading Vault responses, WebSocket frames and user-defined rows, the
|
|
115
|
-
* `typeof` *is* that layer.
|
|
116
|
-
* - `no-unsafe-dictionary-type` (442) is right in a business application and
|
|
117
|
-
* wrong here: tables and columns defined at run time have no compile-time
|
|
118
|
-
* schema, which is the product, not a typing gap.
|
|
119
|
-
* - `no-shape-in-symbol-names` (104) matches a substring in identifiers and
|
|
120
|
-
* catches domain words such as `BlueGreenShape`.
|
|
121
|
-
* - `no-module-mocking` (79) is a test-architecture position, not cleanup.
|
|
122
|
-
* - `no-known-value-widening` (201) is the near miss. Of 174 sampled, 96 are
|
|
123
|
-
* `return accumulator` where the object was filled in a loop from run-time
|
|
124
|
-
* keys, so the open dictionary is the honest type and there is no evidence to
|
|
125
|
-
* preserve; the rule reads them as stable consts because assigning a property
|
|
126
|
-
* is not a write to the binding. The 53 real ones -- annotated object
|
|
127
|
-
* literals that should use `satisfies` -- are worth fixing by hand, and are,
|
|
128
|
-
* but not at the price of 96 suppressions. Narrowing the rule to literals
|
|
129
|
-
* would make it worth turning back on.
|
|
130
|
-
*
|
|
131
|
-
* A repository that wants one back enables it in its own `rules` block.
|
|
132
|
-
*/
|
|
133
|
-
declare const ANTI_SLOP_RULES_OFF_BY_DEFAULT: readonly ["no-known-value-widening", "no-module-mocking", "no-runtime-typeof", "no-shape-in-symbol-names", "no-unknown-parameters", "no-unknown-returns", "no-unsafe-dictionary-type", "require-safety-comment-for-type-assertion"];
|
|
43
|
+
/** Every vendored anti-slop rule, also used to lint this package from source. */
|
|
134
44
|
declare const ANTI_SLOP_RULES: readonly ["no-chained-type-assertions", "no-conditional-empty-object-spread", "no-known-value-widening", "no-module-mocking", "no-object-parameters", "no-reflect-apply", "no-reflect-get", "no-runtime-typeof", "no-shape-in-symbol-names", "no-unknown-parameters", "no-unknown-returns", "no-unknown-type-aliases", "no-unsafe-dictionary-type", "no-widen-then-assert", "require-safety-comment-for-type-assertion"];
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
45
|
+
/** All vendored rules at one severity, without resolving the published plugin. */
|
|
46
|
+
declare function antiSlopRules(severity?: Severity): Record<string, Severity>;
|
|
47
|
+
/** Jest matcher semantics and module restrictions are not portable to Mocha, Chai, and Vitest. */
|
|
48
|
+
declare const FRAMEWORK_SPECIFIC_JEST_RULES: {
|
|
49
|
+
readonly "jest/no-conditional-expect": "off";
|
|
50
|
+
readonly "jest/no-export": "off";
|
|
51
|
+
readonly "jest/no-standalone-expect": "off";
|
|
52
|
+
readonly "jest/prefer-snapshot-hint": "off";
|
|
53
|
+
readonly "jest/require-to-throw-message": "off";
|
|
54
|
+
readonly "jest/valid-expect": "off";
|
|
55
|
+
readonly "jest/valid-expect-in-promise": "off";
|
|
56
|
+
};
|
|
57
|
+
/** Source and published registration share test overrides without Jest framework detection. */
|
|
58
|
+
declare function guardrailsRules(): {
|
|
59
|
+
plugins: "jest"[];
|
|
60
|
+
rules: {
|
|
61
|
+
"jest/expect-expect": "off";
|
|
62
|
+
"antelopejs/no-comments": "error";
|
|
63
|
+
"jest/no-conditional-expect": "off";
|
|
64
|
+
"jest/no-export": "off";
|
|
65
|
+
"jest/no-standalone-expect": "off";
|
|
66
|
+
"jest/prefer-snapshot-hint": "off";
|
|
67
|
+
"jest/require-to-throw-message": "off";
|
|
68
|
+
"jest/valid-expect": "off";
|
|
69
|
+
"jest/valid-expect-in-promise": "off";
|
|
70
|
+
};
|
|
71
|
+
overrides: ({
|
|
72
|
+
files: string[];
|
|
73
|
+
rules: {
|
|
74
|
+
"antelopejs/no-fs-read-in-tests": "error";
|
|
75
|
+
"antelopejs/no-constant-value-assertion": "error";
|
|
76
|
+
"antelopejs/no-typeof-function-only-test": "error";
|
|
77
|
+
"antelopejs/require-assertion": "error";
|
|
78
|
+
};
|
|
79
|
+
} | {
|
|
80
|
+
files: string[];
|
|
81
|
+
rules: {
|
|
82
|
+
"antelopejs/no-fs-read-in-tests": "off";
|
|
83
|
+
"antelopejs/no-constant-value-assertion"?: undefined;
|
|
84
|
+
"antelopejs/no-typeof-function-only-test"?: undefined;
|
|
85
|
+
"antelopejs/require-assertion"?: undefined;
|
|
86
|
+
};
|
|
87
|
+
})[];
|
|
88
|
+
};
|
|
89
|
+
/** The shared AntelopeJS preset. Every enabled rule fails CI; recorded debt is enforced by the ratchet. */
|
|
158
90
|
declare function antelopePreset(options?: AntelopePresetOptions): {
|
|
159
91
|
extends: ({
|
|
160
92
|
categories: {
|
|
@@ -174,21 +106,21 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
|
|
|
174
106
|
}];
|
|
175
107
|
"eslint/radix": "error";
|
|
176
108
|
"eslint/prefer-regex-literals": "error";
|
|
177
|
-
"import/no-cycle":
|
|
109
|
+
"import/no-cycle": "off" | "error";
|
|
178
110
|
"import/no-self-import": "error";
|
|
179
111
|
"import/no-duplicates": "error";
|
|
180
112
|
};
|
|
181
113
|
} | {
|
|
182
114
|
rules: {
|
|
183
115
|
"typescript/no-floating-promises": "error";
|
|
184
|
-
"typescript/await-thenable": "
|
|
185
|
-
"typescript/unbound-method": "
|
|
186
|
-
"typescript/no-meaningless-void-operator": "
|
|
187
|
-
"typescript/no-misused-spread": "
|
|
188
|
-
"typescript/no-base-to-string": "
|
|
189
|
-
"typescript/no-redundant-type-constituents": "
|
|
190
|
-
"typescript/restrict-template-expressions": "
|
|
191
|
-
"typescript/require-array-sort-compare": "
|
|
116
|
+
"typescript/await-thenable": "error";
|
|
117
|
+
"typescript/unbound-method": "error";
|
|
118
|
+
"typescript/no-meaningless-void-operator": "error";
|
|
119
|
+
"typescript/no-misused-spread": "error";
|
|
120
|
+
"typescript/no-base-to-string": "error";
|
|
121
|
+
"typescript/no-redundant-type-constituents": "error";
|
|
122
|
+
"typescript/restrict-template-expressions": "error";
|
|
123
|
+
"typescript/require-array-sort-compare": "error";
|
|
192
124
|
};
|
|
193
125
|
} | {
|
|
194
126
|
jsPlugins: {
|
|
@@ -196,25 +128,61 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
|
|
|
196
128
|
specifier: string;
|
|
197
129
|
}[];
|
|
198
130
|
rules: Record<string, Severity>;
|
|
131
|
+
} | {
|
|
132
|
+
extends: {
|
|
133
|
+
plugins: "jest"[];
|
|
134
|
+
rules: {
|
|
135
|
+
"jest/expect-expect": "off";
|
|
136
|
+
"antelopejs/no-comments": "error";
|
|
137
|
+
"jest/no-conditional-expect": "off";
|
|
138
|
+
"jest/no-export": "off";
|
|
139
|
+
"jest/no-standalone-expect": "off";
|
|
140
|
+
"jest/prefer-snapshot-hint": "off";
|
|
141
|
+
"jest/require-to-throw-message": "off";
|
|
142
|
+
"jest/valid-expect": "off";
|
|
143
|
+
"jest/valid-expect-in-promise": "off";
|
|
144
|
+
};
|
|
145
|
+
overrides: ({
|
|
146
|
+
files: string[];
|
|
147
|
+
rules: {
|
|
148
|
+
"antelopejs/no-fs-read-in-tests": "error";
|
|
149
|
+
"antelopejs/no-constant-value-assertion": "error";
|
|
150
|
+
"antelopejs/no-typeof-function-only-test": "error";
|
|
151
|
+
"antelopejs/require-assertion": "error";
|
|
152
|
+
};
|
|
153
|
+
} | {
|
|
154
|
+
files: string[];
|
|
155
|
+
rules: {
|
|
156
|
+
"antelopejs/no-fs-read-in-tests": "off";
|
|
157
|
+
"antelopejs/no-constant-value-assertion"?: undefined;
|
|
158
|
+
"antelopejs/no-typeof-function-only-test"?: undefined;
|
|
159
|
+
"antelopejs/require-assertion"?: undefined;
|
|
160
|
+
};
|
|
161
|
+
})[];
|
|
162
|
+
}[];
|
|
163
|
+
jsPlugins: {
|
|
164
|
+
name: string;
|
|
165
|
+
specifier: string;
|
|
166
|
+
}[];
|
|
199
167
|
} | {
|
|
200
168
|
rules: {
|
|
201
|
-
"eslint/max-params": [
|
|
169
|
+
"eslint/max-params": ["error", {
|
|
202
170
|
max: number;
|
|
203
171
|
}];
|
|
204
|
-
"eslint/max-lines-per-function": [
|
|
172
|
+
"eslint/max-lines-per-function": ["error", {
|
|
205
173
|
max: number;
|
|
206
174
|
skipBlankLines: true;
|
|
207
175
|
skipComments: true;
|
|
208
176
|
}];
|
|
209
|
-
"eslint/max-lines": [
|
|
177
|
+
"eslint/max-lines": ["error", {
|
|
210
178
|
max: number;
|
|
211
179
|
skipBlankLines: true;
|
|
212
180
|
skipComments: true;
|
|
213
181
|
}];
|
|
214
|
-
"eslint/max-depth": [
|
|
182
|
+
"eslint/max-depth": ["error", {
|
|
215
183
|
max: number;
|
|
216
184
|
}];
|
|
217
|
-
"eslint/complexity": [
|
|
185
|
+
"eslint/complexity": ["error", {
|
|
218
186
|
max: number;
|
|
219
187
|
}];
|
|
220
188
|
};
|
|
@@ -233,6 +201,15 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
|
|
|
233
201
|
rules: {
|
|
234
202
|
"typescript/no-floating-promises": "off" | "error";
|
|
235
203
|
};
|
|
204
|
+
overrides: ({
|
|
205
|
+
files: string[];
|
|
206
|
+
rules: {
|
|
207
|
+
"eslint/max-lines": "off";
|
|
208
|
+
};
|
|
209
|
+
} | {
|
|
210
|
+
files: string[];
|
|
211
|
+
rules: Record<string, "off">;
|
|
212
|
+
})[];
|
|
236
213
|
};
|
|
237
214
|
//#endregion
|
|
238
|
-
export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES,
|
|
215
|
+
export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ASSERTION_FUNCTION_NAMES, AntelopePresetOptions, ComplexityThresholds, DEFAULT_COMPLEXITY_THRESHOLDS, FRAMEWORK_SPECIFIC_JEST_RULES, TEST_FILE_GLOBS, antelopePreset, antiSlopRules, guardrailsRules };
|
package/dist/oxc/lint.mjs
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as findGitRoot, o as readCeilings } from "../ceilings--pJmhSde.mjs";
|
|
2
|
+
import { n as TEST_FILE_GLOBS, t as ASSERTION_FUNCTION_NAMES } from "../shared-WC0z3y9F.mjs";
|
|
3
|
+
import { n as IGNORE_PATTERNS, t as AGENT_IGNORE_PATTERNS } from "../shared-NC0T8ykm.mjs";
|
|
2
4
|
import { defineConfig } from "oxlint";
|
|
3
5
|
//#region src/oxc/lint.ts
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* them when a repository adds patterns of its own.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* export default defineConfig({
|
|
12
|
-
* extends: [antelopePreset()],
|
|
13
|
-
* ignorePatterns: [...ANTELOPE_IGNORE_PATTERNS, "playground/**"],
|
|
14
|
-
* });
|
|
15
|
-
* ```
|
|
7
|
+
* oxlint replaces rather than merges ignorePatterns across extends.
|
|
8
|
+
* Spread these patterns when adding repository-specific ignores.
|
|
16
9
|
*/
|
|
17
10
|
const ANTELOPE_IGNORE_PATTERNS = [...IGNORE_PATTERNS, ...AGENT_IGNORE_PATTERNS];
|
|
18
11
|
const DEFAULT_COMPLEXITY_THRESHOLDS = {
|
|
@@ -22,50 +15,7 @@ const DEFAULT_COMPLEXITY_THRESHOLDS = {
|
|
|
22
15
|
maxDepth: 4,
|
|
23
16
|
complexity: 20
|
|
24
17
|
};
|
|
25
|
-
/** Every
|
|
26
|
-
/**
|
|
27
|
-
* The anti-slop rules left off by default.
|
|
28
|
-
*
|
|
29
|
-
* Measured across the sixteen cms/dms repositories: these seven produced 3038
|
|
30
|
-
* of the 3429 anti-slop findings, and every sample we read was either the
|
|
31
|
-
* correct idiom or a design change well beyond a lint pass.
|
|
32
|
-
*
|
|
33
|
-
* - `require-safety-comment-for-type-assertion` (1283) is satisfied by writing
|
|
34
|
-
* a comment, so at that volume it manufactures the noise it exists to fight.
|
|
35
|
-
* Removing assertions is the goal; annotating them is not.
|
|
36
|
-
* - `no-unknown-parameters` (566) and `no-unknown-returns` (104) fire on catch
|
|
37
|
-
* handlers, where `unknown` is the only correct type, and on the parsers
|
|
38
|
-
* whose whole job is to take unknown in and hand typed values out.
|
|
39
|
-
* - `no-runtime-typeof` (460) assumes a validation layer above the check. In a
|
|
40
|
-
* CMS reading Vault responses, WebSocket frames and user-defined rows, the
|
|
41
|
-
* `typeof` *is* that layer.
|
|
42
|
-
* - `no-unsafe-dictionary-type` (442) is right in a business application and
|
|
43
|
-
* wrong here: tables and columns defined at run time have no compile-time
|
|
44
|
-
* schema, which is the product, not a typing gap.
|
|
45
|
-
* - `no-shape-in-symbol-names` (104) matches a substring in identifiers and
|
|
46
|
-
* catches domain words such as `BlueGreenShape`.
|
|
47
|
-
* - `no-module-mocking` (79) is a test-architecture position, not cleanup.
|
|
48
|
-
* - `no-known-value-widening` (201) is the near miss. Of 174 sampled, 96 are
|
|
49
|
-
* `return accumulator` where the object was filled in a loop from run-time
|
|
50
|
-
* keys, so the open dictionary is the honest type and there is no evidence to
|
|
51
|
-
* preserve; the rule reads them as stable consts because assigning a property
|
|
52
|
-
* is not a write to the binding. The 53 real ones -- annotated object
|
|
53
|
-
* literals that should use `satisfies` -- are worth fixing by hand, and are,
|
|
54
|
-
* but not at the price of 96 suppressions. Narrowing the rule to literals
|
|
55
|
-
* would make it worth turning back on.
|
|
56
|
-
*
|
|
57
|
-
* A repository that wants one back enables it in its own `rules` block.
|
|
58
|
-
*/
|
|
59
|
-
const ANTI_SLOP_RULES_OFF_BY_DEFAULT = [
|
|
60
|
-
"no-known-value-widening",
|
|
61
|
-
"no-module-mocking",
|
|
62
|
-
"no-runtime-typeof",
|
|
63
|
-
"no-shape-in-symbol-names",
|
|
64
|
-
"no-unknown-parameters",
|
|
65
|
-
"no-unknown-returns",
|
|
66
|
-
"no-unsafe-dictionary-type",
|
|
67
|
-
"require-safety-comment-for-type-assertion"
|
|
68
|
-
];
|
|
18
|
+
/** Every vendored anti-slop rule, also used to lint this package from source. */
|
|
69
19
|
const ANTI_SLOP_RULES = [
|
|
70
20
|
"no-chained-type-assertions",
|
|
71
21
|
"no-conditional-empty-object-spread",
|
|
@@ -83,14 +33,8 @@ const ANTI_SLOP_RULES = [
|
|
|
83
33
|
"no-widen-then-assert",
|
|
84
34
|
"require-safety-comment-for-type-assertion"
|
|
85
35
|
];
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
function severityOf(option, fallback) {
|
|
89
|
-
if (option === void 0 || option === true) return fallback;
|
|
90
|
-
if (option === false) return "off";
|
|
91
|
-
return option;
|
|
92
|
-
}
|
|
93
|
-
function basePreset(cycleSeverity) {
|
|
36
|
+
/** Correctness must fail CI; underscore bindings and omitted rest siblings are intentional. */
|
|
37
|
+
function basePreset(importCycles) {
|
|
94
38
|
return defineConfig({
|
|
95
39
|
categories: { correctness: "error" },
|
|
96
40
|
ignorePatterns: ANTELOPE_IGNORE_PATTERNS,
|
|
@@ -116,66 +60,102 @@ function basePreset(cycleSeverity) {
|
|
|
116
60
|
],
|
|
117
61
|
"eslint/radix": "error",
|
|
118
62
|
"eslint/prefer-regex-literals": "error",
|
|
119
|
-
"import/no-cycle":
|
|
63
|
+
"import/no-cycle": importCycles ? "error" : "off",
|
|
120
64
|
"import/no-self-import": "error",
|
|
121
65
|
"import/no-duplicates": "error"
|
|
122
66
|
}
|
|
123
67
|
});
|
|
124
68
|
}
|
|
125
|
-
/**
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
* so linting never waits on a build.
|
|
129
|
-
*/
|
|
130
|
-
function antiSlopRules(severity) {
|
|
131
|
-
const off = new Set(ANTI_SLOP_RULES_OFF_BY_DEFAULT);
|
|
132
|
-
return Object.fromEntries(ANTI_SLOP_RULES.map((rule) => [`anti-slop/${rule}`, off.has(rule) ? "off" : severity]));
|
|
69
|
+
/** All vendored rules at one severity, without resolving the published plugin. */
|
|
70
|
+
function antiSlopRules(severity = "error") {
|
|
71
|
+
return Object.fromEntries(ANTI_SLOP_RULES.map((rule) => [`anti-slop/${rule}`, severity]));
|
|
133
72
|
}
|
|
134
|
-
function antiSlopPreset(
|
|
73
|
+
function antiSlopPreset() {
|
|
135
74
|
return defineConfig({
|
|
136
75
|
jsPlugins: [{
|
|
137
76
|
name: "anti-slop",
|
|
138
77
|
specifier: "@antelopejs/tooling-configs/oxc/anti-slop"
|
|
139
78
|
}],
|
|
140
|
-
rules: antiSlopRules(
|
|
79
|
+
rules: antiSlopRules()
|
|
141
80
|
});
|
|
142
81
|
}
|
|
143
|
-
|
|
82
|
+
/** Jest matcher semantics and module restrictions are not portable to Mocha, Chai, and Vitest. */
|
|
83
|
+
const FRAMEWORK_SPECIFIC_JEST_RULES = {
|
|
84
|
+
"jest/no-conditional-expect": "off",
|
|
85
|
+
"jest/no-export": "off",
|
|
86
|
+
"jest/no-standalone-expect": "off",
|
|
87
|
+
"jest/prefer-snapshot-hint": "off",
|
|
88
|
+
"jest/require-to-throw-message": "off",
|
|
89
|
+
"jest/valid-expect": "off",
|
|
90
|
+
"jest/valid-expect-in-promise": "off"
|
|
91
|
+
};
|
|
92
|
+
/** Source and published registration share test overrides without Jest framework detection. */
|
|
93
|
+
function guardrailsRules() {
|
|
94
|
+
return defineConfig({
|
|
95
|
+
plugins: ["jest"],
|
|
96
|
+
rules: {
|
|
97
|
+
...FRAMEWORK_SPECIFIC_JEST_RULES,
|
|
98
|
+
"jest/expect-expect": "off",
|
|
99
|
+
"antelopejs/no-comments": "error"
|
|
100
|
+
},
|
|
101
|
+
overrides: [{
|
|
102
|
+
files: TEST_FILE_GLOBS,
|
|
103
|
+
rules: {
|
|
104
|
+
"antelopejs/no-fs-read-in-tests": "error",
|
|
105
|
+
"antelopejs/no-constant-value-assertion": "error",
|
|
106
|
+
"antelopejs/no-typeof-function-only-test": "error",
|
|
107
|
+
"antelopejs/require-assertion": "error"
|
|
108
|
+
}
|
|
109
|
+
}, {
|
|
110
|
+
files: [
|
|
111
|
+
"**/fixtures/**",
|
|
112
|
+
"**/helpers/**",
|
|
113
|
+
"**/locales/**"
|
|
114
|
+
],
|
|
115
|
+
rules: { "antelopejs/no-fs-read-in-tests": "off" }
|
|
116
|
+
}]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function guardrailsPreset() {
|
|
120
|
+
return defineConfig({
|
|
121
|
+
extends: [guardrailsRules()],
|
|
122
|
+
jsPlugins: [{
|
|
123
|
+
name: "antelopejs",
|
|
124
|
+
specifier: "@antelopejs/tooling-configs/oxc/guardrails"
|
|
125
|
+
}]
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function complexityPreset(thresholds) {
|
|
144
129
|
return defineConfig({ rules: {
|
|
145
|
-
"eslint/max-params": [
|
|
146
|
-
"eslint/max-lines-per-function": [
|
|
130
|
+
"eslint/max-params": ["error", { max: thresholds.maxParams }],
|
|
131
|
+
"eslint/max-lines-per-function": ["error", {
|
|
147
132
|
max: thresholds.maxLinesPerFunction,
|
|
148
133
|
skipBlankLines: true,
|
|
149
134
|
skipComments: true
|
|
150
135
|
}],
|
|
151
|
-
"eslint/max-lines": [
|
|
136
|
+
"eslint/max-lines": ["error", {
|
|
152
137
|
max: thresholds.maxLines,
|
|
153
138
|
skipBlankLines: true,
|
|
154
139
|
skipComments: true
|
|
155
140
|
}],
|
|
156
|
-
"eslint/max-depth": [
|
|
157
|
-
"eslint/complexity": [
|
|
141
|
+
"eslint/max-depth": ["error", { max: thresholds.maxDepth }],
|
|
142
|
+
"eslint/complexity": ["error", { max: thresholds.complexity }]
|
|
158
143
|
} });
|
|
159
144
|
}
|
|
160
|
-
/**
|
|
161
|
-
* Turning on type information enables a whole family of rules, not just the one
|
|
162
|
-
* worth the setup. `no-floating-promises` catches a promise whose rejection is
|
|
163
|
-
* lost, which is why type-aware linting is worth running at all; the rest report
|
|
164
|
-
* until a repository has worked through them, like every other backlog here.
|
|
165
|
-
*/
|
|
166
145
|
function typeAwarePreset() {
|
|
167
146
|
return defineConfig({ rules: {
|
|
168
147
|
"typescript/no-floating-promises": "error",
|
|
169
|
-
"typescript/await-thenable": "
|
|
170
|
-
"typescript/unbound-method": "
|
|
171
|
-
"typescript/no-meaningless-void-operator": "
|
|
172
|
-
"typescript/no-misused-spread": "
|
|
173
|
-
"typescript/no-base-to-string": "
|
|
174
|
-
"typescript/no-redundant-type-constituents": "
|
|
175
|
-
"typescript/restrict-template-expressions": "
|
|
176
|
-
"typescript/require-array-sort-compare": "
|
|
148
|
+
"typescript/await-thenable": "error",
|
|
149
|
+
"typescript/unbound-method": "error",
|
|
150
|
+
"typescript/no-meaningless-void-operator": "error",
|
|
151
|
+
"typescript/no-misused-spread": "error",
|
|
152
|
+
"typescript/no-base-to-string": "error",
|
|
153
|
+
"typescript/no-redundant-type-constituents": "error",
|
|
154
|
+
"typescript/restrict-template-expressions": "error",
|
|
155
|
+
"typescript/require-array-sort-compare": "error"
|
|
177
156
|
} });
|
|
178
157
|
}
|
|
158
|
+
/** Side-effect imports register classes, so sorting may never relocate them. */
|
|
179
159
|
function importSortingPreset() {
|
|
180
160
|
return defineConfig({
|
|
181
161
|
jsPlugins: ["eslint-plugin-perfectionist"],
|
|
@@ -196,43 +176,38 @@ function importSortingPreset() {
|
|
|
196
176
|
}] }
|
|
197
177
|
});
|
|
198
178
|
}
|
|
199
|
-
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
* });
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
179
|
+
/** Overrides run after rules, including test-specific rules; measurement bypasses all ceilings. */
|
|
180
|
+
function ratchetOverrides() {
|
|
181
|
+
if (process.env["ANTELOPEJS_RATCHET_MEASURE"] !== void 0) return [];
|
|
182
|
+
const ceilings = readCeilings(findGitRoot());
|
|
183
|
+
const rules = Object.fromEntries(Object.keys(ceilings.rules).map((rule) => [rule, "off"]));
|
|
184
|
+
return [...Object.keys(ceilings.oversizeFiles).map((path) => ({
|
|
185
|
+
files: [path.replaceAll(/([*?[\]{}])/gu, "\\$1")],
|
|
186
|
+
rules: { "eslint/max-lines": "off" }
|
|
187
|
+
})), {
|
|
188
|
+
files: ["**/*"],
|
|
189
|
+
rules
|
|
190
|
+
}];
|
|
191
|
+
}
|
|
192
|
+
/** The shared AntelopeJS preset. Every enabled rule fails CI; recorded debt is enforced by the ratchet. */
|
|
216
193
|
function antelopePreset(options = {}) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
...DEFAULT_COMPLEXITY_THRESHOLDS,
|
|
222
|
-
...overrides
|
|
194
|
+
let thresholds = DEFAULT_COMPLEXITY_THRESHOLDS;
|
|
195
|
+
if (options.complexity !== true && options.complexity !== false && options.complexity !== void 0) thresholds = {
|
|
196
|
+
...thresholds,
|
|
197
|
+
...options.complexity
|
|
223
198
|
};
|
|
224
|
-
const complexitySeverity = severityOf(isToggle ? complexity : overrides.severity ?? true, "warn");
|
|
225
|
-
const antiSlopSeverity = severityOf(options.antiSlop, "warn");
|
|
226
199
|
return defineConfig({
|
|
227
200
|
extends: [
|
|
228
|
-
basePreset(
|
|
201
|
+
basePreset(options.importCycles !== false),
|
|
229
202
|
options.typeAware === false ? null : typeAwarePreset(),
|
|
230
|
-
|
|
231
|
-
|
|
203
|
+
options.antiSlop === false ? null : antiSlopPreset(),
|
|
204
|
+
options.guardrails === false ? null : guardrailsPreset(),
|
|
205
|
+
options.complexity === false ? null : complexityPreset(thresholds),
|
|
232
206
|
options.importSorting === true ? importSortingPreset() : null
|
|
233
207
|
].filter((config) => config !== null),
|
|
234
|
-
rules: { "typescript/no-floating-promises": options.typeAware === false ? "off" : "error" }
|
|
208
|
+
rules: { "typescript/no-floating-promises": options.typeAware === false ? "off" : "error" },
|
|
209
|
+
overrides: ratchetOverrides()
|
|
235
210
|
});
|
|
236
211
|
}
|
|
237
212
|
//#endregion
|
|
238
|
-
export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES,
|
|
213
|
+
export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ASSERTION_FUNCTION_NAMES, DEFAULT_COMPLEXITY_THRESHOLDS, FRAMEWORK_SPECIFIC_JEST_RULES, TEST_FILE_GLOBS, antelopePreset, antiSlopRules, guardrailsRules };
|