@hublo/sentinel 1.6.0-alpha.0 → 1.6.0-alpha.2
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 +4 -3
- package/dist/bin/sentinel.js +23 -10
- package/dist/{chunk-NAFI7OLI.js → chunk-4EIY7TTR.js} +22 -8
- package/dist/chunk-4EIY7TTR.js.map +1 -0
- package/dist/{chunk-P7NYSMLS.js → chunk-67QLOX6F.js} +2737 -28
- package/dist/{chunk-5VNYQIFD.js → chunk-EESVRILJ.js} +1 -1
- package/dist/{chunk-5VNYQIFD.js.map → chunk-EESVRILJ.js.map} +1 -1
- package/dist/{chunk-PC5R4DX5.js → chunk-R7DS7VN4.js} +178 -2658
- package/dist/index.js +3 -3
- package/dist/roles/env/config.js +1 -1
- package/dist/roles/test/nest/toolchain.js +1 -1
- package/dist/roles/test/react/toolchain.js +1 -1
- package/dist/roles/test/shared-test-config.js +1 -1
- package/dist/{validate-5SD5CTTO.js → validate-NP7X6XCG.js} +1 -1
- package/docs/env-adoption.md +46 -1
- package/docs/lint-adoption.md +87 -6
- package/docs/using-sentinel.md +10 -10
- package/docs/validating-a-change.md +99 -3
- package/package.json +1 -1
- package/dist/chunk-NAFI7OLI.js.map +0 -1
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
LINT_BASELINE_SPECIFIER,
|
|
10
10
|
LINT_CONFIG_FILE,
|
|
11
11
|
LINT_MEASURE_FILE,
|
|
12
|
+
LINT_PRESETS,
|
|
12
13
|
LINT_SCRIPT_NAME,
|
|
13
14
|
OWNED_WHEN_SET_KEYS,
|
|
14
15
|
PERMITTED_LOCAL_KEYS,
|
|
@@ -23,17 +24,24 @@ import {
|
|
|
23
24
|
canonicalRuleName,
|
|
24
25
|
describeHolds,
|
|
25
26
|
describeRuleKey,
|
|
27
|
+
disabledFor,
|
|
28
|
+
downgradedFor,
|
|
26
29
|
extendsWithBaseline,
|
|
27
30
|
extendsWithPreset,
|
|
28
31
|
formatPresetFor,
|
|
29
32
|
formatPresetName,
|
|
30
33
|
formatTargets,
|
|
34
|
+
governedRules,
|
|
35
|
+
hasLintPreset,
|
|
31
36
|
heldRules,
|
|
32
37
|
holdsFrom,
|
|
38
|
+
isOffRuleValue,
|
|
33
39
|
isSentinelPreset,
|
|
40
|
+
lintPresetFor,
|
|
34
41
|
lintTarget,
|
|
35
42
|
localOnlyKeys,
|
|
36
43
|
manifestOperation,
|
|
44
|
+
moduleOwnBlocks,
|
|
37
45
|
moduleScripts,
|
|
38
46
|
nxTargetOperations,
|
|
39
47
|
oxfmtRejects,
|
|
@@ -48,6 +56,7 @@ import {
|
|
|
48
56
|
readAdoption,
|
|
49
57
|
readFormatAdoption,
|
|
50
58
|
readLintAdoption,
|
|
59
|
+
readModuleAdditions,
|
|
51
60
|
renderBaseline,
|
|
52
61
|
resolveBin,
|
|
53
62
|
resolveConfigTarget,
|
|
@@ -57,9 +66,10 @@ import {
|
|
|
57
66
|
scriptPath,
|
|
58
67
|
selfCommand,
|
|
59
68
|
splitToolArgs,
|
|
69
|
+
uncoveredFor,
|
|
60
70
|
walk,
|
|
61
71
|
writtenFileFormatter
|
|
62
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-67QLOX6F.js";
|
|
63
73
|
import {
|
|
64
74
|
DEFAULT_MAX_DIAGNOSTICS,
|
|
65
75
|
WORKSPACE_ROOT_MARKER,
|
|
@@ -84,7 +94,7 @@ import {
|
|
|
84
94
|
} from "./chunk-7E6YTTAK.js";
|
|
85
95
|
import {
|
|
86
96
|
defineEnv
|
|
87
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-4EIY7TTR.js";
|
|
88
98
|
import {
|
|
89
99
|
globToRegExp
|
|
90
100
|
} from "./chunk-O7REVMOC.js";
|
|
@@ -192,7 +202,15 @@ var shared_default = {
|
|
|
192
202
|
".spec.js",
|
|
193
203
|
".test.js",
|
|
194
204
|
".spec.jsx",
|
|
195
|
-
".test.jsx"
|
|
205
|
+
".test.jsx",
|
|
206
|
+
".spec.mts",
|
|
207
|
+
".test.mts",
|
|
208
|
+
".spec.cts",
|
|
209
|
+
".test.cts",
|
|
210
|
+
".spec.mjs",
|
|
211
|
+
".test.mjs",
|
|
212
|
+
".spec.cjs",
|
|
213
|
+
".test.cjs"
|
|
196
214
|
],
|
|
197
215
|
excludeDirs: ["node_modules", "dist"]
|
|
198
216
|
},
|
|
@@ -1400,16 +1418,25 @@ function deriveVars(files, readers) {
|
|
|
1400
1418
|
return { required, optional };
|
|
1401
1419
|
}
|
|
1402
1420
|
var ENV_LINE = /^(?:export\s+)?([\w.-]+)\s*=(.*)$/;
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1421
|
+
var QUOTES = /* @__PURE__ */ new Set(['"', "'", "`"]);
|
|
1422
|
+
function closingQuote(text, quote, from) {
|
|
1423
|
+
for (let index = from; index < text.length; index += 1) {
|
|
1424
|
+
if (text[index] === "\\" && text[index + 1] === quote) index += 1;
|
|
1425
|
+
else if (text[index] === quote) return index;
|
|
1426
|
+
}
|
|
1427
|
+
return -1;
|
|
1428
|
+
}
|
|
1429
|
+
function readValue(raw) {
|
|
1430
|
+
const value = raw.trimStart();
|
|
1431
|
+
const quote = value[0];
|
|
1432
|
+
if (quote !== void 0 && QUOTES.has(quote)) {
|
|
1433
|
+
const end = closingQuote(value, quote, 1);
|
|
1434
|
+
if (end === -1) return { blank: false, opens: quote };
|
|
1435
|
+
const rest = value.slice(end + 1).trim();
|
|
1436
|
+
return { blank: end === 1 && (rest === "" || rest.startsWith("#")) };
|
|
1437
|
+
}
|
|
1438
|
+
const comment = /\s#/.exec(raw);
|
|
1439
|
+
return { blank: (comment ? raw.slice(0, comment.index) : raw).trim() === "" };
|
|
1413
1440
|
}
|
|
1414
1441
|
function parseEnvFile(content) {
|
|
1415
1442
|
const entries = [];
|
|
@@ -1418,15 +1445,15 @@ function parseEnvFile(content) {
|
|
|
1418
1445
|
for (const [index, rawLine] of lines.entries()) {
|
|
1419
1446
|
const line = rawLine.trim();
|
|
1420
1447
|
if (closing !== void 0) {
|
|
1421
|
-
if (line
|
|
1448
|
+
if (closingQuote(line, closing, 0) !== -1) closing = void 0;
|
|
1422
1449
|
continue;
|
|
1423
1450
|
}
|
|
1424
1451
|
if (line === "" || line.startsWith("#")) continue;
|
|
1425
1452
|
const match = ENV_LINE.exec(line);
|
|
1426
1453
|
if (!match) continue;
|
|
1427
|
-
const
|
|
1428
|
-
entries.push({ key: match[1] ?? "", line: index + 1, blank
|
|
1429
|
-
closing =
|
|
1454
|
+
const { blank, opens } = readValue(match[2] ?? "");
|
|
1455
|
+
entries.push({ key: match[1] ?? "", line: index + 1, blank });
|
|
1456
|
+
closing = opens;
|
|
1430
1457
|
}
|
|
1431
1458
|
return {
|
|
1432
1459
|
entries,
|
|
@@ -2267,9 +2294,15 @@ function escapeData(text) {
|
|
|
2267
2294
|
function escapeProperty(text) {
|
|
2268
2295
|
return escapeData(text).replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
2269
2296
|
}
|
|
2297
|
+
var GITHUB_ANNOTATION_CAP = 10;
|
|
2298
|
+
function summaryAnnotation(command, count, level) {
|
|
2299
|
+
const what = command === "error" ? "blocking findings" : level === "error" ? "advisory findings" : "findings";
|
|
2300
|
+
const message = `${count} ${what} (GitHub shows at most ${GITHUB_ANNOTATION_CAP} ${command} annotations per step): the full list is in the env report, in this step's log, and in env-report/env.md with --output markdown`;
|
|
2301
|
+
return `::${command} title=${escapeProperty(`env: ${count} ${what}`)}::${escapeData(message)}`;
|
|
2302
|
+
}
|
|
2270
2303
|
function renderAnnotations(report) {
|
|
2271
2304
|
if (report.level === "info") return [];
|
|
2272
|
-
|
|
2305
|
+
const annotations = report.findings.filter((entry) => entry.severity !== "info").map((entry) => {
|
|
2273
2306
|
const command = report.level === "error" && entry.severity === "blocking" ? "error" : "warning";
|
|
2274
2307
|
const properties = [
|
|
2275
2308
|
entry.file === void 0 ? void 0 : `file=${escapeProperty(entry.file)}`,
|
|
@@ -2277,8 +2310,13 @@ function renderAnnotations(report) {
|
|
|
2277
2310
|
`title=${escapeProperty(`env rule ${entry.number}: ${entry.rule}`)}`
|
|
2278
2311
|
].filter(Boolean);
|
|
2279
2312
|
const message = `${entry.name}${entry.detail ? ` (${entry.detail})` : ""}: ${RULES[entry.rule].help}`;
|
|
2280
|
-
return `::${command} ${properties.join(",")}::${escapeData(message)}
|
|
2313
|
+
return { command, line: `::${command} ${properties.join(",")}::${escapeData(message)}` };
|
|
2281
2314
|
});
|
|
2315
|
+
const summaries = ["error", "warning"].flatMap((command) => {
|
|
2316
|
+
const count = annotations.filter((entry) => entry.command === command).length;
|
|
2317
|
+
return count > GITHUB_ANNOTATION_CAP ? [summaryAnnotation(command, count, report.level)] : [];
|
|
2318
|
+
});
|
|
2319
|
+
return [...summaries, ...annotations.map((entry) => entry.line)];
|
|
2282
2320
|
}
|
|
2283
2321
|
|
|
2284
2322
|
// src/roles/env/adapters/conformance/conformance.adapter.ts
|
|
@@ -2311,6 +2349,10 @@ function writeShapes(root, report, shapes) {
|
|
|
2311
2349
|
return `${REPORT_DIR2}/${name}`;
|
|
2312
2350
|
});
|
|
2313
2351
|
}
|
|
2352
|
+
function oneLine(message) {
|
|
2353
|
+
const [head = "", ...rest] = message.split("\n").map((line) => line.trim().replace(/^- /, "")).filter((line) => line !== "");
|
|
2354
|
+
return rest.length === 0 ? head : `${head} ${rest.join("; ")}`;
|
|
2355
|
+
}
|
|
2314
2356
|
var ConformanceAdapter = class extends BaseAdapter {
|
|
2315
2357
|
target = TARGET2;
|
|
2316
2358
|
runner = "conformance";
|
|
@@ -2345,17 +2387,17 @@ var ConformanceAdapter = class extends BaseAdapter {
|
|
|
2345
2387
|
`writes ${ENV_SHAPES.join(", ")}; not ${unknown.join(", ")}, which another role may write.`
|
|
2346
2388
|
);
|
|
2347
2389
|
}
|
|
2390
|
+
const refuse = (message) => {
|
|
2391
|
+
this.say(message);
|
|
2392
|
+
return { ok: false, code: 1, metrics: { level, error: oneLine(message) } };
|
|
2393
|
+
};
|
|
2348
2394
|
const { settings, from, unreadable } = await loadEnvConfig(ctx.cwd);
|
|
2349
|
-
if (unreadable)
|
|
2350
|
-
this.say(unreadable);
|
|
2351
|
-
return { ok: false, code: 1 };
|
|
2352
|
-
}
|
|
2395
|
+
if (unreadable) return refuse(unreadable);
|
|
2353
2396
|
let report;
|
|
2354
2397
|
try {
|
|
2355
2398
|
report = collectEnvReport(openRepository(ctx.cwd), settings, level, from);
|
|
2356
2399
|
} catch (error) {
|
|
2357
|
-
|
|
2358
|
-
return { ok: false, code: 1 };
|
|
2400
|
+
return refuse(error instanceof Error ? error.message : String(error));
|
|
2359
2401
|
}
|
|
2360
2402
|
if (printing) {
|
|
2361
2403
|
const written = writeShapes(ctx.cwd, report, known);
|
|
@@ -3214,2516 +3256,92 @@ var OxfmtAdapter = class extends BaseAdapter {
|
|
|
3214
3256
|
* linter is about to change. An existing format segment is left exactly where the module
|
|
3215
3257
|
* already had it, since moving it would be churn for no gain.
|
|
3216
3258
|
*
|
|
3217
|
-
* The dedicated `format` / `format:fix` scripts stay, for running the formatter alone.
|
|
3218
|
-
*/
|
|
3219
|
-
joinFormatIntoLint(original, rewritten, selfCommand2) {
|
|
3220
|
-
const command = selfCommand2 ?? SENTINEL_FORMAT_COMMAND;
|
|
3221
|
-
for (const [name, keepFix] of [
|
|
3222
|
-
["lint", false],
|
|
3223
|
-
["lint:fix", true]
|
|
3224
|
-
]) {
|
|
3225
|
-
const script = rewritten[name] ?? original[name];
|
|
3226
|
-
if (!script || script.trim() === "") continue;
|
|
3227
|
-
if (invokesFormat(script)) continue;
|
|
3228
|
-
rewritten[name] = `${script} && ${keepFix ? `${command} --fix` : command}`;
|
|
3229
|
-
}
|
|
3230
|
-
return rewritten;
|
|
3231
|
-
}
|
|
3232
|
-
};
|
|
3233
|
-
|
|
3234
|
-
// src/roles/format/register.ts
|
|
3235
|
-
function registerFormat() {
|
|
3236
|
-
register(new OxfmtAdapter());
|
|
3237
|
-
setDefaultRunner("format", "oxfmt");
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
|
-
// src/roles/lint/adapters/oxlint/oxlint.adapter.ts
|
|
3241
|
-
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
3242
|
-
import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3243
|
-
import { join as join21 } from "node:path";
|
|
3244
|
-
|
|
3245
|
-
// src/core/config/deferred-rules.ts
|
|
3246
|
-
function deferredRuleNames(rules) {
|
|
3247
|
-
return rules.map((entry) => entry.rule);
|
|
3248
|
-
}
|
|
3249
|
-
|
|
3250
|
-
// src/core/fix-report.ts
|
|
3251
|
-
import { statSync as statSync3 } from "node:fs";
|
|
3252
|
-
import { join as join16 } from "node:path";
|
|
3253
|
-
var CONFIG_REFUSED = /failed to parse .*config|invalid config file/i;
|
|
3254
|
-
function readFailure(output) {
|
|
3255
|
-
const lines = output.split("\n").map((line2) => line2.trim());
|
|
3256
|
-
if (!lines.some((line2) => CONFIG_REFUSED.test(line2))) return void 0;
|
|
3257
|
-
const detail = lines.find((line2) => /invalid config file/i.test(line2));
|
|
3258
|
-
const line = (detail ?? lines.find((entry) => entry !== "") ?? "").replace(/^x\s*/, "");
|
|
3259
|
-
return line.split(/:\s*Failed to parse config/i)[0] ?? line;
|
|
3260
|
-
}
|
|
3261
|
-
function fingerprint(path2) {
|
|
3262
|
-
try {
|
|
3263
|
-
const stat = statSync3(path2);
|
|
3264
|
-
return `${stat.size}:${stat.mtimeMs}`;
|
|
3265
|
-
} catch {
|
|
3266
|
-
return void 0;
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
function snapshotFiles(cwd, extensions) {
|
|
3270
|
-
const snapshot = /* @__PURE__ */ new Map();
|
|
3271
|
-
for (const file of listSourceFiles(cwd, extensions)) {
|
|
3272
|
-
const mark = fingerprint(join16(cwd, file));
|
|
3273
|
-
if (mark !== void 0) snapshot.set(file, mark);
|
|
3274
|
-
}
|
|
3275
|
-
return snapshot;
|
|
3276
|
-
}
|
|
3277
|
-
function changedSince(cwd, before, extensions) {
|
|
3278
|
-
const changed = [];
|
|
3279
|
-
for (const file of listSourceFiles(cwd, extensions)) {
|
|
3280
|
-
const now = fingerprint(join16(cwd, file));
|
|
3281
|
-
if (now === void 0) continue;
|
|
3282
|
-
if (before.get(file) !== now) changed.push(file);
|
|
3283
|
-
}
|
|
3284
|
-
return changed.sort();
|
|
3285
|
-
}
|
|
3286
|
-
var NAMED_IN_REPORT = 5;
|
|
3287
|
-
var NOT_INSTALLED_YET = /invalid config file[\s\S]*node_modules/i;
|
|
3288
|
-
function presetNotInstalledYet(failure) {
|
|
3289
|
-
return NOT_INSTALLED_YET.test(failure);
|
|
3290
|
-
}
|
|
3291
|
-
function describeFixOutcome(outcome, toolLabel) {
|
|
3292
|
-
if (outcome.failure !== void 0) {
|
|
3293
|
-
if (NOT_INSTALLED_YET.test(outcome.failure)) {
|
|
3294
|
-
return `the ${toolLabel} preset is not installed in this module yet, which is expected: this command just added it and the install comes next. Nothing was fixed. Run \`pnpm install\`, then \`sentinel --run --${toolLabel} --fix\` to clear what a machine can clear.`;
|
|
3295
|
-
}
|
|
3296
|
-
return `the ${toolLabel} autofix could not run, so nothing was fixed and this module has not been checked: ${outcome.failure}`;
|
|
3297
|
-
}
|
|
3298
|
-
if (outcome.changed.length === 0) return `the ${toolLabel} autofix changed nothing`;
|
|
3299
|
-
const named = outcome.changed.slice(0, NAMED_IN_REPORT).join(", ");
|
|
3300
|
-
const rest = outcome.changed.length - NAMED_IN_REPORT;
|
|
3301
|
-
const listed = rest > 0 ? `${named} and ${rest} more` : named;
|
|
3302
|
-
return `the ${toolLabel} autofix rewrote ${outcome.changed.length} file${outcome.changed.length === 1 ? "" : "s"}: ${listed}. Review the diff before committing: rules this module used to have switched off are enforced from now on.`;
|
|
3303
|
-
}
|
|
3304
|
-
|
|
3305
|
-
// src/roles/lint/presets/nest.json
|
|
3306
|
-
var nest_default = {
|
|
3307
|
-
plugins: ["typescript", "jest", "vitest", "import", "unicorn", "oxc", "node"],
|
|
3308
|
-
jsPlugins: [
|
|
3309
|
-
"eslint-plugin-no-barrel-files",
|
|
3310
|
-
{
|
|
3311
|
-
name: "nx",
|
|
3312
|
-
specifier: "@nx/eslint-plugin"
|
|
3313
|
-
}
|
|
3314
|
-
],
|
|
3315
|
-
settings: null,
|
|
3316
|
-
rules: {
|
|
3317
|
-
"array-callback-return": [
|
|
3318
|
-
"error",
|
|
3319
|
-
{
|
|
3320
|
-
allowImplicit: false,
|
|
3321
|
-
checkForEach: false,
|
|
3322
|
-
allowVoid: false
|
|
3323
|
-
}
|
|
3324
|
-
],
|
|
3325
|
-
complexity: ["error", 30],
|
|
3326
|
-
curly: ["error", "all"],
|
|
3327
|
-
"dot-notation": [
|
|
3328
|
-
"error",
|
|
3329
|
-
{
|
|
3330
|
-
allowKeywords: true,
|
|
3331
|
-
allowPattern: ""
|
|
3332
|
-
}
|
|
3333
|
-
],
|
|
3334
|
-
eqeqeq: {
|
|
3335
|
-
severity: "warn",
|
|
3336
|
-
reason: "1 pre-existing violation(s) across one module, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero."
|
|
3337
|
-
},
|
|
3338
|
-
"for-direction": "error",
|
|
3339
|
-
"func-style": {
|
|
3340
|
-
severity: "warn",
|
|
3341
|
-
reason: "58 pre-existing violation(s) across network and contract, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
3342
|
-
options: [
|
|
3343
|
-
"expression",
|
|
3344
|
-
{
|
|
3345
|
-
allowArrowFunctions: false,
|
|
3346
|
-
allowTypeAnnotation: false,
|
|
3347
|
-
overrides: {}
|
|
3348
|
-
}
|
|
3349
|
-
]
|
|
3350
|
-
},
|
|
3351
|
-
"import/no-duplicates": [
|
|
3352
|
-
"error",
|
|
3353
|
-
{
|
|
3354
|
-
considerQueryString: true,
|
|
3355
|
-
"prefer-inline": true
|
|
3356
|
-
}
|
|
3357
|
-
],
|
|
3358
|
-
"jest/expect-expect": {
|
|
3359
|
-
severity: "off",
|
|
3360
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3361
|
-
},
|
|
3362
|
-
"jest/no-alias-methods": {
|
|
3363
|
-
severity: "off",
|
|
3364
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3365
|
-
},
|
|
3366
|
-
"jest/no-commented-out-tests": {
|
|
3367
|
-
severity: "off",
|
|
3368
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3369
|
-
},
|
|
3370
|
-
"jest/no-deprecated-functions": "error",
|
|
3371
|
-
"jest/no-disabled-tests": {
|
|
3372
|
-
severity: "off",
|
|
3373
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3374
|
-
},
|
|
3375
|
-
"jest/no-done-callback": "error",
|
|
3376
|
-
"jest/no-export": "error",
|
|
3377
|
-
"jest/no-focused-tests": {
|
|
3378
|
-
severity: "off",
|
|
3379
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3380
|
-
},
|
|
3381
|
-
"jest/no-identical-title": {
|
|
3382
|
-
severity: "off",
|
|
3383
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3384
|
-
},
|
|
3385
|
-
"jest/no-interpolation-in-snapshots": {
|
|
3386
|
-
severity: "off",
|
|
3387
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3388
|
-
},
|
|
3389
|
-
"jest/no-jasmine-globals": "error",
|
|
3390
|
-
"jest/no-mocks-import": {
|
|
3391
|
-
severity: "off",
|
|
3392
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3393
|
-
},
|
|
3394
|
-
"jest/no-standalone-expect": {
|
|
3395
|
-
severity: "off",
|
|
3396
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3397
|
-
},
|
|
3398
|
-
"jest/no-test-prefixes": {
|
|
3399
|
-
severity: "off",
|
|
3400
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3401
|
-
},
|
|
3402
|
-
"jest/prefer-to-be": {
|
|
3403
|
-
severity: "off",
|
|
3404
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3405
|
-
},
|
|
3406
|
-
"jest/prefer-to-contain": {
|
|
3407
|
-
severity: "off",
|
|
3408
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3409
|
-
},
|
|
3410
|
-
"jest/prefer-to-have-length": {
|
|
3411
|
-
severity: "off",
|
|
3412
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3413
|
-
},
|
|
3414
|
-
"jest/valid-describe-callback": {
|
|
3415
|
-
severity: "off",
|
|
3416
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3417
|
-
},
|
|
3418
|
-
"jest/valid-expect": {
|
|
3419
|
-
severity: "off",
|
|
3420
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3421
|
-
},
|
|
3422
|
-
"jest/valid-expect-in-promise": {
|
|
3423
|
-
severity: "off",
|
|
3424
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3425
|
-
},
|
|
3426
|
-
"jest/valid-title": {
|
|
3427
|
-
severity: "off",
|
|
3428
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
3429
|
-
},
|
|
3430
|
-
"no-async-promise-executor": "error",
|
|
3431
|
-
"no-barrel-files/no-barrel-files": {
|
|
3432
|
-
severity: "off",
|
|
3433
|
-
reason: "nest modules use barrel index.ts files as a deliberate structural pattern; the rule fired 127 times and every one was the architecture working as intended"
|
|
3434
|
-
},
|
|
3435
|
-
"no-case-declarations": "error",
|
|
3436
|
-
"no-compare-neg-zero": "error",
|
|
3437
|
-
"no-cond-assign": ["error", "except-parens"],
|
|
3438
|
-
"no-console": {
|
|
3439
|
-
severity: "warn",
|
|
3440
|
-
reason: "61 pre-existing violation(s) across network, db-client-management and others, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
3441
|
-
options: [
|
|
3442
|
-
{
|
|
3443
|
-
allow: ["warn", "error"]
|
|
3444
|
-
}
|
|
3445
|
-
]
|
|
3446
|
-
},
|
|
3447
|
-
"no-constant-binary-expression": "error",
|
|
3448
|
-
"no-constant-condition": [
|
|
3449
|
-
"error",
|
|
3450
|
-
{
|
|
3451
|
-
checkLoops: "allExceptWhileTrue"
|
|
3452
|
-
}
|
|
3453
|
-
],
|
|
3454
|
-
"no-control-regex": {
|
|
3455
|
-
severity: "off",
|
|
3456
|
-
reason: "the single occurrence is a regex whose whole purpose is stripping ASCII control characters before XML output, which the rule cannot distinguish from an accident"
|
|
3457
|
-
},
|
|
3458
|
-
"no-debugger": "error",
|
|
3459
|
-
"no-delete-var": "error",
|
|
3460
|
-
"no-dupe-else-if": "error",
|
|
3461
|
-
"no-dupe-keys": "error",
|
|
3462
|
-
"no-duplicate-case": "error",
|
|
3463
|
-
"no-else-return": [
|
|
3464
|
-
"error",
|
|
3465
|
-
{
|
|
3466
|
-
allowElseIf: true
|
|
3467
|
-
}
|
|
3468
|
-
],
|
|
3469
|
-
"no-empty": [
|
|
3470
|
-
"error",
|
|
3471
|
-
{
|
|
3472
|
-
allowEmptyCatch: false
|
|
3473
|
-
}
|
|
3474
|
-
],
|
|
3475
|
-
"no-empty-character-class": "error",
|
|
3476
|
-
"no-empty-pattern": [
|
|
3477
|
-
"error",
|
|
3478
|
-
{
|
|
3479
|
-
allowObjectPatternsAsParameters: false
|
|
3480
|
-
}
|
|
3481
|
-
],
|
|
3482
|
-
"no-empty-static-block": "error",
|
|
3483
|
-
"no-ex-assign": "error",
|
|
3484
|
-
"no-extra-boolean-cast": ["error", {}],
|
|
3485
|
-
"no-fallthrough": [
|
|
3486
|
-
"error",
|
|
3487
|
-
{
|
|
3488
|
-
allowEmptyCase: false,
|
|
3489
|
-
reportUnusedFallthroughComment: false
|
|
3490
|
-
}
|
|
3491
|
-
],
|
|
3492
|
-
"no-global-assign": [
|
|
3493
|
-
"error",
|
|
3494
|
-
{
|
|
3495
|
-
exceptions: []
|
|
3496
|
-
}
|
|
3497
|
-
],
|
|
3498
|
-
"no-implicit-coercion": [
|
|
3499
|
-
"error",
|
|
3500
|
-
{
|
|
3501
|
-
allow: [],
|
|
3502
|
-
boolean: true,
|
|
3503
|
-
disallowTemplateShorthand: false,
|
|
3504
|
-
number: true,
|
|
3505
|
-
string: true
|
|
3506
|
-
}
|
|
3507
|
-
],
|
|
3508
|
-
"no-invalid-regexp": ["error", {}],
|
|
3509
|
-
"no-irregular-whitespace": [
|
|
3510
|
-
"error",
|
|
3511
|
-
{
|
|
3512
|
-
skipComments: false,
|
|
3513
|
-
skipJSXText: false,
|
|
3514
|
-
skipRegExps: false,
|
|
3515
|
-
skipStrings: true,
|
|
3516
|
-
skipTemplates: false
|
|
3517
|
-
}
|
|
3518
|
-
],
|
|
3519
|
-
"no-lonely-if": "error",
|
|
3520
|
-
"no-loss-of-precision": "error",
|
|
3521
|
-
"no-misleading-character-class": "error",
|
|
3522
|
-
"no-nonoctal-decimal-escape": "error",
|
|
3523
|
-
"no-prototype-builtins": "error",
|
|
3524
|
-
"no-regex-spaces": "error",
|
|
3525
|
-
"no-restricted-imports": [
|
|
3526
|
-
"error",
|
|
3527
|
-
{
|
|
3528
|
-
paths: [
|
|
3529
|
-
{
|
|
3530
|
-
name: "@front/theme",
|
|
3531
|
-
importNames: [
|
|
3532
|
-
"hubloTheme",
|
|
3533
|
-
"legacyHubloTheme",
|
|
3534
|
-
"customCommonColors",
|
|
3535
|
-
"customPalette",
|
|
3536
|
-
"breakpointsOptions",
|
|
3537
|
-
"breakpointsValues",
|
|
3538
|
-
"spacingConstants"
|
|
3539
|
-
],
|
|
3540
|
-
message: "Use the MUI theme context or the public providers exposed by @front/theme."
|
|
3541
|
-
}
|
|
3542
|
-
],
|
|
3543
|
-
patterns: [
|
|
3544
|
-
{
|
|
3545
|
-
group: ["@front/theme/*", "!@front/theme/testing"],
|
|
3546
|
-
message: "Deep imports from @front/theme are forbidden outside the theme lib."
|
|
3547
|
-
}
|
|
3548
|
-
]
|
|
3549
|
-
}
|
|
3550
|
-
],
|
|
3551
|
-
"no-self-assign": [
|
|
3552
|
-
"error",
|
|
3553
|
-
{
|
|
3554
|
-
props: true
|
|
3555
|
-
}
|
|
3556
|
-
],
|
|
3557
|
-
"no-shadow-restricted-names": [
|
|
3558
|
-
"error",
|
|
3559
|
-
{
|
|
3560
|
-
reportGlobalThis: false
|
|
3561
|
-
}
|
|
3562
|
-
],
|
|
3563
|
-
"no-sparse-arrays": "error",
|
|
3564
|
-
"no-unneeded-ternary": [
|
|
3565
|
-
"error",
|
|
3566
|
-
{
|
|
3567
|
-
defaultAssignment: true
|
|
3568
|
-
}
|
|
3569
|
-
],
|
|
3570
|
-
"no-unsafe-finally": "error",
|
|
3571
|
-
"no-unsafe-optional-chaining": {
|
|
3572
|
-
severity: "warn",
|
|
3573
|
-
reason: "7 pre-existing violation(s) across the db-* libs, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
3574
|
-
options: [
|
|
3575
|
-
{
|
|
3576
|
-
disallowArithmeticOperators: false
|
|
3577
|
-
}
|
|
3578
|
-
]
|
|
3579
|
-
},
|
|
3580
|
-
"no-unused-labels": "error",
|
|
3581
|
-
"no-unused-private-class-members": "error",
|
|
3582
|
-
"no-useless-backreference": "error",
|
|
3583
|
-
"no-useless-catch": "error",
|
|
3584
|
-
"no-useless-escape": [
|
|
3585
|
-
"error",
|
|
3586
|
-
{
|
|
3587
|
-
allowRegexCharacters: []
|
|
3588
|
-
}
|
|
3589
|
-
],
|
|
3590
|
-
"no-useless-return": "error",
|
|
3591
|
-
"nx/enforce-module-boundaries": [
|
|
3592
|
-
"error",
|
|
3593
|
-
{
|
|
3594
|
-
enforceBuildableLibDependency: true,
|
|
3595
|
-
allow: [],
|
|
3596
|
-
depConstraints: [
|
|
3597
|
-
{
|
|
3598
|
-
sourceTag: "*",
|
|
3599
|
-
onlyDependOnLibsWithTags: ["*"]
|
|
3600
|
-
}
|
|
3601
|
-
]
|
|
3602
|
-
}
|
|
3603
|
-
],
|
|
3604
|
-
"prefer-arrow-callback": [
|
|
3605
|
-
"error",
|
|
3606
|
-
{
|
|
3607
|
-
allowNamedFunctions: false,
|
|
3608
|
-
allowUnboundThis: true
|
|
3609
|
-
}
|
|
3610
|
-
],
|
|
3611
|
-
"require-yield": "error",
|
|
3612
|
-
"typescript/await-thenable": "error",
|
|
3613
|
-
"typescript/no-confusing-non-null-assertion": "error",
|
|
3614
|
-
"typescript/no-empty-function": {
|
|
3615
|
-
severity: "warn",
|
|
3616
|
-
reason: "pre-existing violations that were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
3617
|
-
options: [
|
|
3618
|
-
{
|
|
3619
|
-
allow: []
|
|
3620
|
-
}
|
|
3621
|
-
]
|
|
3622
|
-
},
|
|
3623
|
-
"typescript/no-explicit-any": "error",
|
|
3624
|
-
"typescript/no-floating-promises": [
|
|
3625
|
-
"error",
|
|
3626
|
-
{
|
|
3627
|
-
ignoreVoid: true
|
|
3628
|
-
}
|
|
3629
|
-
],
|
|
3630
|
-
"typescript/no-import-type-side-effects": "error",
|
|
3631
|
-
"typescript/no-inferrable-types": "error",
|
|
3632
|
-
"typescript/no-non-null-assertion": "error",
|
|
3633
|
-
"typescript/no-unused-vars": {
|
|
3634
|
-
severity: "warn",
|
|
3635
|
-
reason: "pre-existing violations that were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
3636
|
-
options: [
|
|
3637
|
-
{
|
|
3638
|
-
argsIgnorePattern: "^_",
|
|
3639
|
-
caughtErrors: "none"
|
|
3640
|
-
}
|
|
3641
|
-
]
|
|
3642
|
-
},
|
|
3643
|
-
"typescript/return-await": {
|
|
3644
|
-
severity: "warn",
|
|
3645
|
-
reason: "replaces the deprecated core `no-return-await`, which both modules set to error but which was never actually reporting: the nx lint target expanded to 2 files of 2888. `in-try-catch` rather than `never`, and the planning adoption is what settled it. `never` forces `return await f()` to become `const x = await f(); return x` even inside a `try`, where the await is REQUIRED for the catch to fire: it produced 10 such edits across 15 modules, every one of them inside a try/catch, and every one of them a rewrite that made the code longer without making it safer. Worse, the obvious reading of the rule is to delete the `await`, which silently stops the catch from running. `in-try-catch` is what typescript-eslint recommends and flags none of those 10. Held at warn so adoption does not turn a green module red, and raised to error once the remaining findings are fixed.",
|
|
3646
|
-
options: ["in-try-catch"]
|
|
3647
|
-
},
|
|
3648
|
-
"typescript/switch-exhaustiveness-check": [
|
|
3649
|
-
"error",
|
|
3650
|
-
{
|
|
3651
|
-
considerDefaultExhaustiveForUnions: true
|
|
3652
|
-
}
|
|
3653
|
-
],
|
|
3654
|
-
"use-isnan": [
|
|
3655
|
-
"error",
|
|
3656
|
-
{
|
|
3657
|
-
enforceForIndexOf: false,
|
|
3658
|
-
enforceForSwitchCase: true
|
|
3659
|
-
}
|
|
3660
|
-
],
|
|
3661
|
-
"valid-typeof": [
|
|
3662
|
-
"error",
|
|
3663
|
-
{
|
|
3664
|
-
requireStringLiterals: false
|
|
3665
|
-
}
|
|
3666
|
-
],
|
|
3667
|
-
"vitest/expect-expect": {
|
|
3668
|
-
severity: "warn",
|
|
3669
|
-
reason: "the modules already ran this at warn (confirmed in the bff-admin proof-of-concept config); adoption is like-for-like, so raising it to error is a separate decision"
|
|
3670
|
-
},
|
|
3671
|
-
"vitest/no-alias-methods": "error",
|
|
3672
|
-
"vitest/no-commented-out-tests": {
|
|
3673
|
-
severity: "warn",
|
|
3674
|
-
reason: "the modules already ran this at warn (confirmed in the bff-admin proof-of-concept config); adoption is like-for-like, so raising it to error is a separate decision"
|
|
3675
|
-
},
|
|
3676
|
-
"vitest/no-conditional-expect": {
|
|
3677
|
-
severity: "warn",
|
|
3678
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
3679
|
-
},
|
|
3680
|
-
"vitest/no-disabled-tests": {
|
|
3681
|
-
severity: "warn",
|
|
3682
|
-
reason: "the modules already ran this at warn (confirmed in the bff-admin proof-of-concept config); a skipped test is a deliberate act often paired with a ticket, so it reports rather than blocks"
|
|
3683
|
-
},
|
|
3684
|
-
"vitest/no-focused-tests": "error",
|
|
3685
|
-
"vitest/no-identical-title": "error",
|
|
3686
|
-
"vitest/no-interpolation-in-snapshots": "error",
|
|
3687
|
-
"vitest/no-mocks-import": "error",
|
|
3688
|
-
"vitest/no-standalone-expect": "error",
|
|
3689
|
-
"vitest/no-test-prefixes": "error",
|
|
3690
|
-
"vitest/prefer-to-be": "error",
|
|
3691
|
-
"vitest/prefer-to-contain": "error",
|
|
3692
|
-
"vitest/prefer-to-have-length": "error",
|
|
3693
|
-
"vitest/require-mock-type-parameters": {
|
|
3694
|
-
severity: "off",
|
|
3695
|
-
reason: "4 479 of the 5 255 findings this plugin reports over this repository, 85% of them. It asks for type parameters on vi.fn<\u2026>(), a convention this codebase never had; adopting it is its own piece of work and not part of reading the right plugin"
|
|
3696
|
-
},
|
|
3697
|
-
"vitest/require-to-throw-message": {
|
|
3698
|
-
severity: "warn",
|
|
3699
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
3700
|
-
},
|
|
3701
|
-
"vitest/valid-describe-callback": "error",
|
|
3702
|
-
"vitest/valid-expect": {
|
|
3703
|
-
severity: "warn",
|
|
3704
|
-
reason: "1 pre-existing violation(s) across bdd-tooling, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero."
|
|
3705
|
-
},
|
|
3706
|
-
"vitest/valid-expect-in-promise": "error",
|
|
3707
|
-
"vitest/valid-title": "error",
|
|
3708
|
-
"vitest/warn-todo": {
|
|
3709
|
-
severity: "warn",
|
|
3710
|
-
reason: "a todo test is a reminder rather than a defect, so it reports and never blocks"
|
|
3711
|
-
}
|
|
3712
|
-
},
|
|
3713
|
-
uncovered: {
|
|
3714
|
-
"array-bracket-newline": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3715
|
-
"array-bracket-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3716
|
-
"block-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3717
|
-
"computed-property-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3718
|
-
"dot-location": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3719
|
-
"eol-last": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3720
|
-
"func-call-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3721
|
-
"import/order": "import ordering is FORMATTING, and the format role owns it: oxfmt's `sortImports` reproduces exactly these groups (builtin, external, internal, parent/index, sibling, alphabetical, blank line between) and sorts a file completely in ONE pass, because it rewrites the whole import block. A lint fixer cannot: it emits text edits over overlapping ranges, so this rule needed several runs to finish (five imports took four passes, measured) and sentinel deliberately runs autofix once. Enforced by `pnpm run format`, not by the linter, which is also why `eslint-plugin-import` is no longer hosted at all: its only other rule, no-duplicates, is native in oxlint.",
|
|
3722
|
-
"key-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3723
|
-
"keyword-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3724
|
-
"lines-between-class-members": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3725
|
-
"no-invalid-this": "no oxlint equivalent, and hosting does not help: the rule crashes on every file under oxlint's plugin API (sourceCode.getJSDocComment is not implemented). Its coverage moves to TypeScript's noImplicitThis, which the sentinel TypeScript role manages.",
|
|
3726
|
-
"no-multi-spaces": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3727
|
-
"no-octal": "no oxlint equivalent",
|
|
3728
|
-
"no-restricted-syntax": "no oxlint equivalent, and unlike the react tier this preset hosts no house-rule plugin, so architectural guards written as AST selectors are not enforced at all. They belong in sentinel's `hublo` plugin, next to the frontend ones: tell us which guards your service relies on. A per-module copy of a house rule drifts, which is the problem sentinel exists to remove.",
|
|
3729
|
-
"no-trailing-spaces": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3730
|
-
semi: "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3731
|
-
"template-curly-spacing": "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between.",
|
|
3732
|
-
"typescript/member-ordering": "oxlint has no native rule for it, and the preset deliberately does NOT host @typescript-eslint/eslint-plugin: hosting a whole plugin for one rule costs a dependency, a load step and a pass over every file. Accepted as a loss rather than paid for, the same call as no-octal."
|
|
3733
|
-
},
|
|
3734
|
-
overrides: [
|
|
3735
|
-
{
|
|
3736
|
-
files: [
|
|
3737
|
-
"**/*.test.ts",
|
|
3738
|
-
"**/*.test.tsx",
|
|
3739
|
-
"**/*.spec.ts",
|
|
3740
|
-
"**/*.spec.tsx",
|
|
3741
|
-
"**/*.integration-spec.ts",
|
|
3742
|
-
"**/*.e2e-spec.ts"
|
|
3743
|
-
],
|
|
3744
|
-
rules: {
|
|
3745
|
-
"no-restricted-properties": {
|
|
3746
|
-
severity: "warn",
|
|
3747
|
-
reason: "held at warn: over the 8 011 test files, 7 call Math.random(), 104 call Date.now(), 3 crypto.randomUUID(), 1 performance.now() and 1 process.hrtime, and 28 of the files that read the clock already install fake timers. A warning says it without turning a suite that was green yesterday red. Verified at error on a fixture carrying all nine forms: these six are reported, new Date('2026-01-01') is not, which is the point",
|
|
3748
|
-
options: [
|
|
3749
|
-
{
|
|
3750
|
-
object: "Math",
|
|
3751
|
-
property: "random",
|
|
3752
|
-
message: "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
3753
|
-
},
|
|
3754
|
-
{
|
|
3755
|
-
object: "Date",
|
|
3756
|
-
property: "now",
|
|
3757
|
-
message: "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3758
|
-
},
|
|
3759
|
-
{
|
|
3760
|
-
object: "performance",
|
|
3761
|
-
property: "now",
|
|
3762
|
-
message: "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3763
|
-
},
|
|
3764
|
-
{
|
|
3765
|
-
object: "process",
|
|
3766
|
-
property: "hrtime",
|
|
3767
|
-
message: "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3768
|
-
},
|
|
3769
|
-
{
|
|
3770
|
-
object: "crypto",
|
|
3771
|
-
property: "randomUUID",
|
|
3772
|
-
message: "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
3773
|
-
},
|
|
3774
|
-
{
|
|
3775
|
-
object: "crypto",
|
|
3776
|
-
property: "getRandomValues",
|
|
3777
|
-
message: "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
3778
|
-
}
|
|
3779
|
-
]
|
|
3780
|
-
},
|
|
3781
|
-
"no-restricted-globals": {
|
|
3782
|
-
severity: "warn",
|
|
3783
|
-
reason: "held at warn: 68 test files call setTimeout and only 2 of them install fake timers, so waiting on the real clock is the second source of flakiness after reading it. The flush idiom await new Promise((resolve) => setTimeout(resolve, 0)) is inside that count and is usually harmless, which is exactly why this reports and never blocks",
|
|
3784
|
-
options: [
|
|
3785
|
-
{
|
|
3786
|
-
name: "setTimeout",
|
|
3787
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
3788
|
-
},
|
|
3789
|
-
{
|
|
3790
|
-
name: "setInterval",
|
|
3791
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
3792
|
-
}
|
|
3793
|
-
]
|
|
3794
|
-
}
|
|
3795
|
-
}
|
|
3796
|
-
}
|
|
3797
|
-
]
|
|
3798
|
-
};
|
|
3799
|
-
|
|
3800
|
-
// src/roles/lint/presets/node.json
|
|
3801
|
-
var node_default = {
|
|
3802
|
-
plugins: ["typescript", "oxc", "vitest"],
|
|
3803
|
-
jsPlugins: [],
|
|
3804
|
-
settings: null,
|
|
3805
|
-
rules: {
|
|
3806
|
-
"typescript/no-unused-expressions": {
|
|
3807
|
-
severity: "warn",
|
|
3808
|
-
reason: "3 pre-existing violations in apps/cloud/institution, never reported because the nx eslint target matched a couple of files per module. Held at warn so adoption stays a lateral move; the debt is visible in `--inspect` and the severity returns once it reaches zero. Parked in the node LAYER rather than the shared base on purpose: the base is the floor every preset stands on, and softening it would weaken presets that have no such debt.",
|
|
3809
|
-
options: [
|
|
3810
|
-
{
|
|
3811
|
-
allowShortCircuit: false,
|
|
3812
|
-
allowTaggedTemplates: false,
|
|
3813
|
-
allowTernary: false
|
|
3814
|
-
}
|
|
3815
|
-
]
|
|
3816
|
-
},
|
|
3817
|
-
"vitest/expect-expect": {
|
|
3818
|
-
severity: "warn",
|
|
3819
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3820
|
-
},
|
|
3821
|
-
"vitest/no-alias-methods": {
|
|
3822
|
-
severity: "warn",
|
|
3823
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3824
|
-
},
|
|
3825
|
-
"vitest/no-commented-out-tests": {
|
|
3826
|
-
severity: "warn",
|
|
3827
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3828
|
-
},
|
|
3829
|
-
"vitest/no-conditional-expect": {
|
|
3830
|
-
severity: "warn",
|
|
3831
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3832
|
-
},
|
|
3833
|
-
"vitest/no-disabled-tests": {
|
|
3834
|
-
severity: "warn",
|
|
3835
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3836
|
-
},
|
|
3837
|
-
"vitest/no-focused-tests": {
|
|
3838
|
-
severity: "warn",
|
|
3839
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3840
|
-
},
|
|
3841
|
-
"vitest/no-identical-title": {
|
|
3842
|
-
severity: "warn",
|
|
3843
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3844
|
-
},
|
|
3845
|
-
"vitest/no-interpolation-in-snapshots": {
|
|
3846
|
-
severity: "warn",
|
|
3847
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3848
|
-
},
|
|
3849
|
-
"vitest/no-mocks-import": {
|
|
3850
|
-
severity: "warn",
|
|
3851
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3852
|
-
},
|
|
3853
|
-
"vitest/no-standalone-expect": {
|
|
3854
|
-
severity: "warn",
|
|
3855
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3856
|
-
},
|
|
3857
|
-
"vitest/no-test-prefixes": {
|
|
3858
|
-
severity: "warn",
|
|
3859
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3860
|
-
},
|
|
3861
|
-
"vitest/prefer-to-be": {
|
|
3862
|
-
severity: "warn",
|
|
3863
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3864
|
-
},
|
|
3865
|
-
"vitest/prefer-to-contain": {
|
|
3866
|
-
severity: "warn",
|
|
3867
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3868
|
-
},
|
|
3869
|
-
"vitest/prefer-to-have-length": {
|
|
3870
|
-
severity: "warn",
|
|
3871
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3872
|
-
},
|
|
3873
|
-
"vitest/require-mock-type-parameters": {
|
|
3874
|
-
severity: "off",
|
|
3875
|
-
reason: "4 479 of the 5 255 findings this plugin reports over this repository, 85% of them. It asks for type parameters on vi.fn<\u2026>(), a convention this codebase never had; adopting it is its own piece of work and not part of reading the right plugin"
|
|
3876
|
-
},
|
|
3877
|
-
"vitest/require-to-throw-message": {
|
|
3878
|
-
severity: "warn",
|
|
3879
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3880
|
-
},
|
|
3881
|
-
"vitest/valid-describe-callback": {
|
|
3882
|
-
severity: "warn",
|
|
3883
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3884
|
-
},
|
|
3885
|
-
"vitest/valid-expect": {
|
|
3886
|
-
severity: "warn",
|
|
3887
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3888
|
-
},
|
|
3889
|
-
"vitest/valid-expect-in-promise": {
|
|
3890
|
-
severity: "warn",
|
|
3891
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3892
|
-
},
|
|
3893
|
-
"vitest/valid-title": {
|
|
3894
|
-
severity: "warn",
|
|
3895
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3896
|
-
},
|
|
3897
|
-
"vitest/warn-todo": {
|
|
3898
|
-
severity: "warn",
|
|
3899
|
-
reason: "the backend tier runs tests and this preset carried no test rule at all, so the whole set ships at warn: it reports and never blocks a suite that was green yesterday"
|
|
3900
|
-
}
|
|
3901
|
-
},
|
|
3902
|
-
overrides: [
|
|
3903
|
-
{
|
|
3904
|
-
files: [
|
|
3905
|
-
"**/*.test.ts",
|
|
3906
|
-
"**/*.test.tsx",
|
|
3907
|
-
"**/*.spec.ts",
|
|
3908
|
-
"**/*.spec.tsx",
|
|
3909
|
-
"**/*.integration-spec.ts",
|
|
3910
|
-
"**/*.e2e-spec.ts"
|
|
3911
|
-
],
|
|
3912
|
-
rules: {
|
|
3913
|
-
"no-restricted-properties": {
|
|
3914
|
-
severity: "warn",
|
|
3915
|
-
reason: "held at warn: over the 8 011 test files, 7 call Math.random(), 104 call Date.now(), 3 crypto.randomUUID(), 1 performance.now() and 1 process.hrtime, and 28 of the files that read the clock already install fake timers. A warning says it without turning a suite that was green yesterday red. Verified at error on a fixture carrying all nine forms: these six are reported, new Date('2026-01-01') is not, which is the point",
|
|
3916
|
-
options: [
|
|
3917
|
-
{
|
|
3918
|
-
object: "Math",
|
|
3919
|
-
property: "random",
|
|
3920
|
-
message: "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
3921
|
-
},
|
|
3922
|
-
{
|
|
3923
|
-
object: "Date",
|
|
3924
|
-
property: "now",
|
|
3925
|
-
message: "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3926
|
-
},
|
|
3927
|
-
{
|
|
3928
|
-
object: "performance",
|
|
3929
|
-
property: "now",
|
|
3930
|
-
message: "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3931
|
-
},
|
|
3932
|
-
{
|
|
3933
|
-
object: "process",
|
|
3934
|
-
property: "hrtime",
|
|
3935
|
-
message: "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
3936
|
-
},
|
|
3937
|
-
{
|
|
3938
|
-
object: "crypto",
|
|
3939
|
-
property: "randomUUID",
|
|
3940
|
-
message: "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
3941
|
-
},
|
|
3942
|
-
{
|
|
3943
|
-
object: "crypto",
|
|
3944
|
-
property: "getRandomValues",
|
|
3945
|
-
message: "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
3946
|
-
}
|
|
3947
|
-
]
|
|
3948
|
-
},
|
|
3949
|
-
"no-restricted-globals": {
|
|
3950
|
-
severity: "warn",
|
|
3951
|
-
reason: "held at warn: 68 test files call setTimeout and only 2 of them install fake timers, so waiting on the real clock is the second source of flakiness after reading it. The flush idiom await new Promise((resolve) => setTimeout(resolve, 0)) is inside that count and is usually harmless, which is exactly why this reports and never blocks",
|
|
3952
|
-
options: [
|
|
3953
|
-
{
|
|
3954
|
-
name: "setTimeout",
|
|
3955
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
3956
|
-
},
|
|
3957
|
-
{
|
|
3958
|
-
name: "setInterval",
|
|
3959
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
3960
|
-
}
|
|
3961
|
-
]
|
|
3962
|
-
}
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
]
|
|
3966
|
-
};
|
|
3967
|
-
|
|
3968
|
-
// src/roles/lint/presets/react-lib.json
|
|
3969
|
-
var react_lib_default = {
|
|
3970
|
-
plugins: ["typescript", "react", "jsx-a11y", "jest", "vitest", "unicorn", "oxc", "nextjs"],
|
|
3971
|
-
jsPlugins: [
|
|
3972
|
-
"eslint-plugin-no-barrel-files",
|
|
3973
|
-
{
|
|
3974
|
-
name: "nx",
|
|
3975
|
-
specifier: "@nx/eslint-plugin"
|
|
3976
|
-
},
|
|
3977
|
-
{
|
|
3978
|
-
name: "jest-dom",
|
|
3979
|
-
specifier: "eslint-plugin-jest-dom"
|
|
3980
|
-
},
|
|
3981
|
-
{
|
|
3982
|
-
name: "storybook",
|
|
3983
|
-
specifier: "eslint-plugin-storybook"
|
|
3984
|
-
},
|
|
3985
|
-
"../plugins/hublo.js",
|
|
3986
|
-
{
|
|
3987
|
-
name: "@tanstack/query",
|
|
3988
|
-
specifier: "@tanstack/eslint-plugin-query"
|
|
3989
|
-
}
|
|
3990
|
-
],
|
|
3991
|
-
settings: null,
|
|
3992
|
-
renames: {
|
|
3993
|
-
"@next/next": "nextjs"
|
|
3994
|
-
},
|
|
3995
|
-
rules: {
|
|
3996
|
-
"@tanstack/query/exhaustive-deps": {
|
|
3997
|
-
severity: "warn",
|
|
3998
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
3999
|
-
},
|
|
4000
|
-
"@tanstack/query/infinite-query-property-order": {
|
|
4001
|
-
severity: "warn",
|
|
4002
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4003
|
-
},
|
|
4004
|
-
"@tanstack/query/mutation-property-order": {
|
|
4005
|
-
severity: "warn",
|
|
4006
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4007
|
-
},
|
|
4008
|
-
"@tanstack/query/no-rest-destructuring": {
|
|
4009
|
-
severity: "warn",
|
|
4010
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4011
|
-
},
|
|
4012
|
-
"@tanstack/query/no-unstable-deps": {
|
|
4013
|
-
severity: "warn",
|
|
4014
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4015
|
-
},
|
|
4016
|
-
"@tanstack/query/no-void-query-fn": {
|
|
4017
|
-
severity: "warn",
|
|
4018
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4019
|
-
},
|
|
4020
|
-
"@tanstack/query/prefer-query-options": {
|
|
4021
|
-
severity: "warn",
|
|
4022
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4023
|
-
},
|
|
4024
|
-
"@tanstack/query/stable-query-client": {
|
|
4025
|
-
severity: "warn",
|
|
4026
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4027
|
-
},
|
|
4028
|
-
curly: ["error", "all"],
|
|
4029
|
-
"for-direction": "error",
|
|
4030
|
-
"hublo/no-regex-lookbehind": "error",
|
|
4031
|
-
"jest-dom/prefer-checked": "error",
|
|
4032
|
-
"jest-dom/prefer-empty": "error",
|
|
4033
|
-
"jest-dom/prefer-enabled-disabled": "error",
|
|
4034
|
-
"jest-dom/prefer-focus": "error",
|
|
4035
|
-
"jest-dom/prefer-in-document": "error",
|
|
4036
|
-
"jest-dom/prefer-required": "error",
|
|
4037
|
-
"jest-dom/prefer-to-have-attribute": "error",
|
|
4038
|
-
"jest-dom/prefer-to-have-class": "error",
|
|
4039
|
-
"jest-dom/prefer-to-have-style": "error",
|
|
4040
|
-
"jest-dom/prefer-to-have-text-content": "error",
|
|
4041
|
-
"jest-dom/prefer-to-have-value": "error",
|
|
4042
|
-
"jest/expect-expect": {
|
|
4043
|
-
severity: "off",
|
|
4044
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4045
|
-
},
|
|
4046
|
-
"jest/no-alias-methods": {
|
|
4047
|
-
severity: "off",
|
|
4048
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4049
|
-
},
|
|
4050
|
-
"jest/no-commented-out-tests": {
|
|
4051
|
-
severity: "off",
|
|
4052
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4053
|
-
},
|
|
4054
|
-
"jest/no-conditional-expect": {
|
|
4055
|
-
severity: "off",
|
|
4056
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4057
|
-
},
|
|
4058
|
-
"jest/no-deprecated-functions": "error",
|
|
4059
|
-
"jest/no-disabled-tests": {
|
|
4060
|
-
severity: "off",
|
|
4061
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4062
|
-
},
|
|
4063
|
-
"jest/no-done-callback": "error",
|
|
4064
|
-
"jest/no-export": "error",
|
|
4065
|
-
"jest/no-focused-tests": {
|
|
4066
|
-
severity: "off",
|
|
4067
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4068
|
-
},
|
|
4069
|
-
"jest/no-identical-title": {
|
|
4070
|
-
severity: "off",
|
|
4071
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4072
|
-
},
|
|
4073
|
-
"jest/no-interpolation-in-snapshots": {
|
|
4074
|
-
severity: "off",
|
|
4075
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4076
|
-
},
|
|
4077
|
-
"jest/no-jasmine-globals": "error",
|
|
4078
|
-
"jest/no-mocks-import": {
|
|
4079
|
-
severity: "off",
|
|
4080
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4081
|
-
},
|
|
4082
|
-
"jest/no-standalone-expect": {
|
|
4083
|
-
severity: "off",
|
|
4084
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4085
|
-
},
|
|
4086
|
-
"jest/no-test-prefixes": {
|
|
4087
|
-
severity: "off",
|
|
4088
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4089
|
-
},
|
|
4090
|
-
"jest/prefer-to-be": {
|
|
4091
|
-
severity: "off",
|
|
4092
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4093
|
-
},
|
|
4094
|
-
"jest/prefer-to-contain": {
|
|
4095
|
-
severity: "off",
|
|
4096
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4097
|
-
},
|
|
4098
|
-
"jest/prefer-to-have-length": {
|
|
4099
|
-
severity: "off",
|
|
4100
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4101
|
-
},
|
|
4102
|
-
"jest/valid-describe-callback": {
|
|
4103
|
-
severity: "off",
|
|
4104
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4105
|
-
},
|
|
4106
|
-
"jest/valid-expect": {
|
|
4107
|
-
severity: "off",
|
|
4108
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4109
|
-
},
|
|
4110
|
-
"jest/valid-expect-in-promise": {
|
|
4111
|
-
severity: "off",
|
|
4112
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4113
|
-
},
|
|
4114
|
-
"jest/valid-title": {
|
|
4115
|
-
severity: "off",
|
|
4116
|
-
reason: "the vitest plugin reports the same violation at the same offset, and this repository runs vitest: measured over apps and libs, 765 of this plugin\u2019s 769 findings are duplicates of the vitest ones. Its rules fire on jest-style files too, so nothing is lost by reading them once"
|
|
4117
|
-
},
|
|
4118
|
-
"jsx-a11y/anchor-is-valid": [
|
|
4119
|
-
"error",
|
|
4120
|
-
{
|
|
4121
|
-
components: ["Link"],
|
|
4122
|
-
specialLink: ["hrefLeft", "hrefRight"],
|
|
4123
|
-
aspects: ["invalidHref", "preferButton"]
|
|
4124
|
-
}
|
|
4125
|
-
],
|
|
4126
|
-
"nextjs/google-font-display": {
|
|
4127
|
-
severity: "warn",
|
|
4128
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4129
|
-
},
|
|
4130
|
-
"nextjs/google-font-preconnect": {
|
|
4131
|
-
severity: "warn",
|
|
4132
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4133
|
-
},
|
|
4134
|
-
"nextjs/inline-script-id": "error",
|
|
4135
|
-
"nextjs/next-script-for-ga": {
|
|
4136
|
-
severity: "warn",
|
|
4137
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4138
|
-
},
|
|
4139
|
-
"nextjs/no-assign-module-variable": "error",
|
|
4140
|
-
"nextjs/no-async-client-component": {
|
|
4141
|
-
severity: "warn",
|
|
4142
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4143
|
-
},
|
|
4144
|
-
"nextjs/no-before-interactive-script-outside-document": {
|
|
4145
|
-
severity: "warn",
|
|
4146
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4147
|
-
},
|
|
4148
|
-
"nextjs/no-css-tags": {
|
|
4149
|
-
severity: "warn",
|
|
4150
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4151
|
-
},
|
|
4152
|
-
"nextjs/no-document-import-in-page": "error",
|
|
4153
|
-
"nextjs/no-duplicate-head": "error",
|
|
4154
|
-
"nextjs/no-head-element": {
|
|
4155
|
-
severity: "warn",
|
|
4156
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4157
|
-
},
|
|
4158
|
-
"nextjs/no-head-import-in-document": "error",
|
|
4159
|
-
"nextjs/no-html-link-for-pages": "error",
|
|
4160
|
-
"nextjs/no-img-element": {
|
|
4161
|
-
severity: "warn",
|
|
4162
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4163
|
-
},
|
|
4164
|
-
"nextjs/no-page-custom-font": {
|
|
4165
|
-
severity: "warn",
|
|
4166
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4167
|
-
},
|
|
4168
|
-
"nextjs/no-script-component-in-head": "error",
|
|
4169
|
-
"nextjs/no-styled-jsx-in-document": {
|
|
4170
|
-
severity: "warn",
|
|
4171
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4172
|
-
},
|
|
4173
|
-
"nextjs/no-sync-scripts": "error",
|
|
4174
|
-
"nextjs/no-title-in-document-head": {
|
|
4175
|
-
severity: "warn",
|
|
4176
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4177
|
-
},
|
|
4178
|
-
"nextjs/no-typos": {
|
|
4179
|
-
severity: "warn",
|
|
4180
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4181
|
-
},
|
|
4182
|
-
"nextjs/no-unwanted-polyfillio": {
|
|
4183
|
-
severity: "warn",
|
|
4184
|
-
reason: "Next's own recommended config sets this at warn, and the libs inherit it. Four of the ten front libs really do import `next` (`components` alone in 40 files), so the rule is not decoration here, but its severity is Next's call rather than ours."
|
|
4185
|
-
},
|
|
4186
|
-
"no-async-promise-executor": "error",
|
|
4187
|
-
"no-barrel-files/no-barrel-files": {
|
|
4188
|
-
severity: "warn",
|
|
4189
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4190
|
-
},
|
|
4191
|
-
"no-case-declarations": "error",
|
|
4192
|
-
"no-compare-neg-zero": "error",
|
|
4193
|
-
"no-cond-assign": ["error", "except-parens"],
|
|
4194
|
-
"no-console": {
|
|
4195
|
-
severity: "warn",
|
|
4196
|
-
reason: "53 pre-existing violation(s) across libs/front/analytics, and they were never reported: the nx eslint target matched a couple of files per module (2 of 2888 on bff-admin), so the rule was configured and not enforced. Held at warn so adoption stays a lateral move rather than turning green modules red for code that predates it; the debt stays visible and countable via `--run --lint --json` and `--inspect`, and the severity is restored once it reaches zero.",
|
|
4197
|
-
options: [
|
|
4198
|
-
{
|
|
4199
|
-
allow: ["warn", "error"]
|
|
4200
|
-
}
|
|
4201
|
-
]
|
|
4202
|
-
},
|
|
4203
|
-
"no-constant-binary-expression": "error",
|
|
4204
|
-
"no-constant-condition": [
|
|
4205
|
-
"error",
|
|
4206
|
-
{
|
|
4207
|
-
checkLoops: "allExceptWhileTrue"
|
|
4208
|
-
}
|
|
4209
|
-
],
|
|
4210
|
-
"no-control-regex": "error",
|
|
4211
|
-
"no-debugger": "error",
|
|
4212
|
-
"no-delete-var": "error",
|
|
4213
|
-
"no-dupe-else-if": "error",
|
|
4214
|
-
"no-duplicate-case": "error",
|
|
4215
|
-
"no-empty": [
|
|
4216
|
-
"error",
|
|
4217
|
-
{
|
|
4218
|
-
allowEmptyCatch: false
|
|
4219
|
-
}
|
|
4220
|
-
],
|
|
4221
|
-
"no-empty-character-class": "error",
|
|
4222
|
-
"no-empty-pattern": [
|
|
4223
|
-
"error",
|
|
4224
|
-
{
|
|
4225
|
-
allowObjectPatternsAsParameters: false
|
|
4226
|
-
}
|
|
4227
|
-
],
|
|
4228
|
-
"no-empty-static-block": "error",
|
|
4229
|
-
"no-ex-assign": "error",
|
|
4230
|
-
"no-extra-boolean-cast": ["error", {}],
|
|
4231
|
-
"no-fallthrough": [
|
|
4232
|
-
"error",
|
|
4233
|
-
{
|
|
4234
|
-
allowEmptyCase: false,
|
|
4235
|
-
reportUnusedFallthroughComment: false
|
|
4236
|
-
}
|
|
4237
|
-
],
|
|
4238
|
-
"no-global-assign": [
|
|
4239
|
-
"error",
|
|
4240
|
-
{
|
|
4241
|
-
exceptions: []
|
|
4242
|
-
}
|
|
4243
|
-
],
|
|
4244
|
-
"no-invalid-regexp": ["error", {}],
|
|
4245
|
-
"no-irregular-whitespace": [
|
|
4246
|
-
"error",
|
|
4247
|
-
{
|
|
4248
|
-
skipComments: false,
|
|
4249
|
-
skipJSXText: false,
|
|
4250
|
-
skipRegExps: false,
|
|
4251
|
-
skipStrings: true,
|
|
4252
|
-
skipTemplates: false
|
|
4253
|
-
}
|
|
4254
|
-
],
|
|
4255
|
-
"no-loss-of-precision": "error",
|
|
4256
|
-
"no-misleading-character-class": "error",
|
|
4257
|
-
"no-nonoctal-decimal-escape": "error",
|
|
4258
|
-
"no-prototype-builtins": "error",
|
|
4259
|
-
"no-regex-spaces": "error",
|
|
4260
|
-
"no-restricted-properties": [
|
|
4261
|
-
"error",
|
|
4262
|
-
{
|
|
4263
|
-
object: "i18n",
|
|
4264
|
-
property: "changeLanguage",
|
|
4265
|
-
message: "This does not work in Nextjs. Please use Link or router instead. See https://nextjs.org/docs/advanced-features/i18n-routing#transition-between-locales"
|
|
4266
|
-
}
|
|
4267
|
-
],
|
|
4268
|
-
"no-self-assign": [
|
|
4269
|
-
"error",
|
|
4270
|
-
{
|
|
4271
|
-
props: true
|
|
4272
|
-
}
|
|
4273
|
-
],
|
|
4274
|
-
"no-shadow-restricted-names": [
|
|
4275
|
-
"error",
|
|
4276
|
-
{
|
|
4277
|
-
reportGlobalThis: false
|
|
4278
|
-
}
|
|
4279
|
-
],
|
|
4280
|
-
"no-sparse-arrays": "error",
|
|
4281
|
-
"no-unsafe-finally": "error",
|
|
4282
|
-
"no-unsafe-optional-chaining": [
|
|
4283
|
-
"error",
|
|
4284
|
-
{
|
|
4285
|
-
disallowArithmeticOperators: false
|
|
4286
|
-
}
|
|
4287
|
-
],
|
|
4288
|
-
"no-unused-labels": "error",
|
|
4289
|
-
"no-unused-private-class-members": "error",
|
|
4290
|
-
"no-useless-backreference": "error",
|
|
4291
|
-
"no-useless-catch": "error",
|
|
4292
|
-
"no-useless-escape": [
|
|
4293
|
-
"error",
|
|
4294
|
-
{
|
|
4295
|
-
allowRegexCharacters: []
|
|
4296
|
-
}
|
|
4297
|
-
],
|
|
4298
|
-
"nx/enforce-module-boundaries": [
|
|
4299
|
-
"error",
|
|
4300
|
-
{
|
|
4301
|
-
enforceBuildableLibDependency: true,
|
|
4302
|
-
allow: [],
|
|
4303
|
-
depConstraints: [
|
|
4304
|
-
{
|
|
4305
|
-
sourceTag: "*",
|
|
4306
|
-
onlyDependOnLibsWithTags: ["*"]
|
|
4307
|
-
}
|
|
4308
|
-
]
|
|
4309
|
-
}
|
|
4310
|
-
],
|
|
4311
|
-
"react-hooks/exhaustive-deps": {
|
|
4312
|
-
severity: "warn",
|
|
4313
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4314
|
-
},
|
|
4315
|
-
"react-hooks/rules-of-hooks": "error",
|
|
4316
|
-
"react/jsx-curly-brace-presence": {
|
|
4317
|
-
severity: "warn",
|
|
4318
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first.",
|
|
4319
|
-
options: [
|
|
4320
|
-
{
|
|
4321
|
-
props: "never",
|
|
4322
|
-
children: "never"
|
|
4323
|
-
}
|
|
4324
|
-
]
|
|
4325
|
-
},
|
|
4326
|
-
"react/jsx-no-useless-fragment": [
|
|
4327
|
-
"error",
|
|
4328
|
-
{
|
|
4329
|
-
allowExpressions: true
|
|
4330
|
-
}
|
|
4331
|
-
],
|
|
4332
|
-
"require-yield": "error",
|
|
4333
|
-
"typescript/consistent-type-imports": [
|
|
4334
|
-
"error",
|
|
4335
|
-
{
|
|
4336
|
-
fixStyle: "inline-type-imports"
|
|
4337
|
-
}
|
|
4338
|
-
],
|
|
4339
|
-
"typescript/no-empty-function": [
|
|
4340
|
-
"error",
|
|
4341
|
-
{
|
|
4342
|
-
allow: []
|
|
4343
|
-
}
|
|
4344
|
-
],
|
|
4345
|
-
"typescript/no-explicit-any": "error",
|
|
4346
|
-
"typescript/no-floating-promises": [
|
|
4347
|
-
"error",
|
|
4348
|
-
{
|
|
4349
|
-
ignoreVoid: true
|
|
4350
|
-
}
|
|
4351
|
-
],
|
|
4352
|
-
"typescript/no-inferrable-types": "error",
|
|
4353
|
-
"typescript/no-non-null-assertion": {
|
|
4354
|
-
severity: "warn",
|
|
4355
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4356
|
-
},
|
|
4357
|
-
"typescript/no-unused-vars": [
|
|
4358
|
-
"error",
|
|
4359
|
-
{
|
|
4360
|
-
argsIgnorePattern: "^_",
|
|
4361
|
-
caughtErrors: "none"
|
|
4362
|
-
}
|
|
4363
|
-
],
|
|
4364
|
-
"typescript/no-useless-constructor": {
|
|
4365
|
-
severity: "warn",
|
|
4366
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4367
|
-
},
|
|
4368
|
-
"typescript/return-await": {
|
|
4369
|
-
severity: "warn",
|
|
4370
|
-
reason: "replaces the deprecated core `no-return-await`, which both modules set to error but which was never actually reporting: the nx lint target expanded to 2 files of 2888. `in-try-catch` rather than `never`, and the planning adoption is what settled it. `never` forces `return await f()` to become `const x = await f(); return x` even inside a `try`, where the await is REQUIRED for the catch to fire: it produced 10 such edits across 15 modules, every one of them inside a try/catch, and every one of them a rewrite that made the code longer without making it safer. Worse, the obvious reading of the rule is to delete the `await`, which silently stops the catch from running. `in-try-catch` is what typescript-eslint recommends and flags none of those 10. Held at warn so adoption does not turn a green module red, and raised to error once the remaining findings are fixed.",
|
|
4371
|
-
options: ["in-try-catch"]
|
|
4372
|
-
},
|
|
4373
|
-
"use-isnan": [
|
|
4374
|
-
"error",
|
|
4375
|
-
{
|
|
4376
|
-
enforceForIndexOf: false,
|
|
4377
|
-
enforceForSwitchCase: true
|
|
4378
|
-
}
|
|
4379
|
-
],
|
|
4380
|
-
"valid-typeof": [
|
|
4381
|
-
"error",
|
|
4382
|
-
{
|
|
4383
|
-
requireStringLiterals: false
|
|
4384
|
-
}
|
|
4385
|
-
],
|
|
4386
|
-
"vitest/expect-expect": [
|
|
4387
|
-
"error",
|
|
4388
|
-
{
|
|
4389
|
-
assertFunctionNames: [
|
|
4390
|
-
"expect",
|
|
4391
|
-
"expect*",
|
|
4392
|
-
"waitForElementToBeRemoved",
|
|
4393
|
-
"screen.findBy*",
|
|
4394
|
-
"result.findBy*"
|
|
4395
|
-
]
|
|
4396
|
-
}
|
|
4397
|
-
],
|
|
4398
|
-
"vitest/no-alias-methods": "error",
|
|
4399
|
-
"vitest/no-commented-out-tests": {
|
|
4400
|
-
severity: "warn",
|
|
4401
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4402
|
-
},
|
|
4403
|
-
"vitest/no-conditional-expect": "error",
|
|
4404
|
-
"vitest/no-disabled-tests": {
|
|
4405
|
-
severity: "warn",
|
|
4406
|
-
reason: "the front libs already run this at warn today (read with `eslint --print-config`), so keeping it there is a like-for-like migration. Raising it to error would be a NEW enforcement decision, and it needs its own count of violations first."
|
|
4407
|
-
},
|
|
4408
|
-
"vitest/no-focused-tests": "error",
|
|
4409
|
-
"vitest/no-identical-title": "error",
|
|
4410
|
-
"vitest/no-interpolation-in-snapshots": "error",
|
|
4411
|
-
"vitest/no-mocks-import": "error",
|
|
4412
|
-
"vitest/no-standalone-expect": "error",
|
|
4413
|
-
"vitest/no-test-prefixes": "error",
|
|
4414
|
-
"vitest/prefer-to-be": "error",
|
|
4415
|
-
"vitest/prefer-to-contain": "error",
|
|
4416
|
-
"vitest/prefer-to-have-length": "error",
|
|
4417
|
-
"vitest/require-mock-type-parameters": {
|
|
4418
|
-
severity: "off",
|
|
4419
|
-
reason: "4 479 of the 5 255 findings this plugin reports over this repository, 85% of them. It asks for type parameters on vi.fn<\u2026>(), a convention this codebase never had; adopting it is its own piece of work and not part of reading the right plugin"
|
|
4420
|
-
},
|
|
4421
|
-
"vitest/require-to-throw-message": {
|
|
4422
|
-
severity: "warn",
|
|
4423
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
4424
|
-
},
|
|
4425
|
-
"vitest/valid-describe-callback": "error",
|
|
4426
|
-
"vitest/valid-expect": "error",
|
|
4427
|
-
"vitest/valid-expect-in-promise": "error",
|
|
4428
|
-
"vitest/valid-title": "error",
|
|
4429
|
-
"vitest/warn-todo": {
|
|
4430
|
-
severity: "warn",
|
|
4431
|
-
reason: "a todo test is a reminder rather than a defect, so it reports and never blocks"
|
|
4432
|
-
}
|
|
4433
|
-
},
|
|
4434
|
-
overrides: [
|
|
4435
|
-
{
|
|
4436
|
-
files: ["**/*.stories.ts", "**/*.stories.tsx", "**/*.stories.js", "**/*.stories.jsx"],
|
|
4437
|
-
rules: {
|
|
4438
|
-
"storybook/await-interactions": "error",
|
|
4439
|
-
"storybook/context-in-play-function": "error",
|
|
4440
|
-
"storybook/default-exports": "error",
|
|
4441
|
-
"storybook/hierarchy-separator": {
|
|
4442
|
-
severity: "warn",
|
|
4443
|
-
reason: "the storybook plugin sets this severity for story files; adoption is like-for-like"
|
|
4444
|
-
},
|
|
4445
|
-
"storybook/no-redundant-story-name": {
|
|
4446
|
-
severity: "warn",
|
|
4447
|
-
reason: "the storybook plugin sets this severity for story files; adoption is like-for-like"
|
|
4448
|
-
},
|
|
4449
|
-
"storybook/no-renderer-packages": "error",
|
|
4450
|
-
"storybook/prefer-pascal-case": {
|
|
4451
|
-
severity: "warn",
|
|
4452
|
-
reason: "the storybook plugin sets this severity for story files; adoption is like-for-like"
|
|
4453
|
-
},
|
|
4454
|
-
"storybook/story-exports": "error",
|
|
4455
|
-
"storybook/use-storybook-expect": "error",
|
|
4456
|
-
"storybook/use-storybook-testing-library": "error",
|
|
4457
|
-
"react-hooks/rules-of-hooks": {
|
|
4458
|
-
severity: "off",
|
|
4459
|
-
reason: "off for story files in the module's own config, and it has to be: a story's render function is not a React component and the rule cannot tell, so it reports every useState in a story. Measured on libs/front/components: 7 errors, none of them real."
|
|
4460
|
-
}
|
|
4461
|
-
}
|
|
4462
|
-
},
|
|
4463
|
-
{
|
|
4464
|
-
files: [
|
|
4465
|
-
"**/*.test.ts",
|
|
4466
|
-
"**/*.test.tsx",
|
|
4467
|
-
"**/*.spec.ts",
|
|
4468
|
-
"**/*.spec.tsx",
|
|
4469
|
-
"**/*.integration-spec.ts",
|
|
4470
|
-
"**/*.e2e-spec.ts"
|
|
4471
|
-
],
|
|
4472
|
-
rules: {
|
|
4473
|
-
"no-restricted-properties": {
|
|
4474
|
-
severity: "warn",
|
|
4475
|
-
reason: "held at warn: over the 8 011 test files, 7 call Math.random(), 104 call Date.now(), 3 crypto.randomUUID(), 1 performance.now() and 1 process.hrtime, and 28 of the files that read the clock already install fake timers. A warning says it without turning a suite that was green yesterday red. Verified at error on a fixture carrying all nine forms: these six are reported, new Date('2026-01-01') is not, which is the point",
|
|
4476
|
-
options: [
|
|
4477
|
-
{
|
|
4478
|
-
object: "Math",
|
|
4479
|
-
property: "random",
|
|
4480
|
-
message: "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
4481
|
-
},
|
|
4482
|
-
{
|
|
4483
|
-
object: "Date",
|
|
4484
|
-
property: "now",
|
|
4485
|
-
message: "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
4486
|
-
},
|
|
4487
|
-
{
|
|
4488
|
-
object: "performance",
|
|
4489
|
-
property: "now",
|
|
4490
|
-
message: "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
4491
|
-
},
|
|
4492
|
-
{
|
|
4493
|
-
object: "process",
|
|
4494
|
-
property: "hrtime",
|
|
4495
|
-
message: "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
4496
|
-
},
|
|
4497
|
-
{
|
|
4498
|
-
object: "crypto",
|
|
4499
|
-
property: "randomUUID",
|
|
4500
|
-
message: "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
4501
|
-
},
|
|
4502
|
-
{
|
|
4503
|
-
object: "crypto",
|
|
4504
|
-
property: "getRandomValues",
|
|
4505
|
-
message: "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
4506
|
-
}
|
|
4507
|
-
]
|
|
4508
|
-
},
|
|
4509
|
-
"no-restricted-globals": {
|
|
4510
|
-
severity: "warn",
|
|
4511
|
-
reason: "held at warn: 68 test files call setTimeout and only 2 of them install fake timers, so waiting on the real clock is the second source of flakiness after reading it. The flush idiom await new Promise((resolve) => setTimeout(resolve, 0)) is inside that count and is usually harmless, which is exactly why this reports and never blocks",
|
|
4512
|
-
options: [
|
|
4513
|
-
{
|
|
4514
|
-
name: "setTimeout",
|
|
4515
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
4516
|
-
},
|
|
4517
|
-
{
|
|
4518
|
-
name: "setInterval",
|
|
4519
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
4520
|
-
}
|
|
4521
|
-
]
|
|
4522
|
-
}
|
|
4523
|
-
}
|
|
4524
|
-
}
|
|
4525
|
-
],
|
|
4526
|
-
uncovered: {
|
|
4527
|
-
"no-octal": "no oxlint equivalent",
|
|
4528
|
-
"no-restricted-syntax": "no oxlint equivalent; the house rules it encoded ship as the local `hublo` plugin instead, so this tier hosts `../plugins/hublo.js` too. It enforces exactly one of them: `hublo/no-regex-lookbehind`, because a library is where that bug is WRITTEN and it reaches an app tier only by being imported (HUB-43431 shipped from libs/front/components into the worker app). The palette selectors stay app-tier only.",
|
|
4529
|
-
semi: "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between."
|
|
4530
|
-
}
|
|
4531
|
-
};
|
|
4532
|
-
|
|
4533
|
-
// src/roles/lint/presets/react.json
|
|
4534
|
-
var react_default = {
|
|
4535
|
-
plugins: ["typescript", "react", "jsx-a11y", "jest", "vitest", "import", "unicorn", "oxc"],
|
|
4536
|
-
jsPlugins: [
|
|
4537
|
-
"eslint-plugin-no-barrel-files",
|
|
4538
|
-
{
|
|
4539
|
-
name: "nx",
|
|
4540
|
-
specifier: "@nx/eslint-plugin"
|
|
4541
|
-
},
|
|
4542
|
-
{
|
|
4543
|
-
name: "@tanstack/query",
|
|
4544
|
-
specifier: "@tanstack/eslint-plugin-query"
|
|
4545
|
-
},
|
|
4546
|
-
{
|
|
4547
|
-
name: "styled-components-a11y",
|
|
4548
|
-
specifier: "eslint-plugin-styled-components-a11y"
|
|
4549
|
-
},
|
|
4550
|
-
{
|
|
4551
|
-
name: "react-refresh",
|
|
4552
|
-
specifier: "eslint-plugin-react-refresh"
|
|
4553
|
-
},
|
|
4554
|
-
"../plugins/hublo.js",
|
|
4555
|
-
{
|
|
4556
|
-
name: "@tanstack/router",
|
|
4557
|
-
specifier: "@tanstack/eslint-plugin-router"
|
|
4558
|
-
}
|
|
4559
|
-
],
|
|
4560
|
-
settings: null,
|
|
4561
|
-
rules: {
|
|
4562
|
-
"@tanstack/query/exhaustive-deps": {
|
|
4563
|
-
severity: "warn",
|
|
4564
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4565
|
-
},
|
|
4566
|
-
"@tanstack/query/infinite-query-property-order": {
|
|
4567
|
-
severity: "warn",
|
|
4568
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4569
|
-
},
|
|
4570
|
-
"@tanstack/query/mutation-property-order": {
|
|
4571
|
-
severity: "warn",
|
|
4572
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4573
|
-
},
|
|
4574
|
-
"@tanstack/query/no-rest-destructuring": {
|
|
4575
|
-
severity: "warn",
|
|
4576
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4577
|
-
},
|
|
4578
|
-
"@tanstack/query/no-unstable-deps": {
|
|
4579
|
-
severity: "warn",
|
|
4580
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4581
|
-
},
|
|
4582
|
-
"@tanstack/query/no-void-query-fn": {
|
|
4583
|
-
severity: "warn",
|
|
4584
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4585
|
-
},
|
|
4586
|
-
"@tanstack/query/prefer-query-options": {
|
|
4587
|
-
severity: "warn",
|
|
4588
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4589
|
-
},
|
|
4590
|
-
"@tanstack/query/stable-query-client": {
|
|
4591
|
-
severity: "warn",
|
|
4592
|
-
reason: "held at warn across the react tier: the plugin is now a dependency of sentinel, so the rule runs everywhere instead of being named by a preset that could not load it. Measured over 8 784 files of console, host-admin, libs/front/api and libs/front/components, the eight rules report 806 findings, of which 796 are prefer-query-options and 10 are the correctness ones (exhaustive-deps 9, no-rest-destructuring 1). A module that wants them to block decides that for itself, and pays the 10 fixes"
|
|
4593
|
-
},
|
|
4594
|
-
"@tanstack/router/create-route-property-order": {
|
|
4595
|
-
severity: "warn",
|
|
4596
|
-
reason: "held at warn on the APP tier only: routes live in applications, and libs/front holds 0 of the 227 files that call createFileRoute, the same reason hublo/require-reload-document is here and not in react-lib. Measured over the three fronts, 7 133 files and 226 route files, the two rules report 3 findings, all create-route-property-order on host-admin. The order is not cosmetic: TanStack Router infers types through it"
|
|
4597
|
-
},
|
|
4598
|
-
"@tanstack/router/route-param-names": {
|
|
4599
|
-
severity: "warn",
|
|
4600
|
-
reason: "held at warn on the APP tier only: routes live in applications, and libs/front holds 0 of the 227 files that call createFileRoute, the same reason hublo/require-reload-document is here and not in react-lib. Measured over the three fronts, 7 133 files and 226 route files, the two rules report 3 findings, all create-route-property-order on host-admin. The order is not cosmetic: TanStack Router infers types through it"
|
|
4601
|
-
},
|
|
4602
|
-
curly: ["error", "all"],
|
|
4603
|
-
"for-direction": "error",
|
|
4604
|
-
"hublo/no-palette-common": {
|
|
4605
|
-
severity: "off",
|
|
4606
|
-
reason: "the house rule finds 3 real violations; they are fixed as their own change rather than inside a linter swap, so the rule ships visible-but-off and can be switched on once they are"
|
|
4607
|
-
},
|
|
4608
|
-
"hublo/no-regex-lookbehind": "error",
|
|
4609
|
-
"hublo/require-reload-document": "error",
|
|
4610
|
-
"jest/expect-expect": {
|
|
4611
|
-
severity: "off",
|
|
4612
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4613
|
-
},
|
|
4614
|
-
"jest/no-alias-methods": {
|
|
4615
|
-
severity: "off",
|
|
4616
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4617
|
-
},
|
|
4618
|
-
"jest/no-commented-out-tests": {
|
|
4619
|
-
severity: "off",
|
|
4620
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4621
|
-
},
|
|
4622
|
-
"jest/no-conditional-expect": {
|
|
4623
|
-
severity: "off",
|
|
4624
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4625
|
-
},
|
|
4626
|
-
"jest/no-deprecated-functions": {
|
|
4627
|
-
severity: "off",
|
|
4628
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4629
|
-
},
|
|
4630
|
-
"jest/no-disabled-tests": {
|
|
4631
|
-
severity: "off",
|
|
4632
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4633
|
-
},
|
|
4634
|
-
"jest/no-done-callback": {
|
|
4635
|
-
severity: "off",
|
|
4636
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4637
|
-
},
|
|
4638
|
-
"jest/no-export": {
|
|
4639
|
-
severity: "off",
|
|
4640
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4641
|
-
},
|
|
4642
|
-
"jest/no-focused-tests": {
|
|
4643
|
-
severity: "off",
|
|
4644
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4645
|
-
},
|
|
4646
|
-
"jest/no-identical-title": {
|
|
4647
|
-
severity: "off",
|
|
4648
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4649
|
-
},
|
|
4650
|
-
"jest/no-interpolation-in-snapshots": {
|
|
4651
|
-
severity: "off",
|
|
4652
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4653
|
-
},
|
|
4654
|
-
"jest/no-jasmine-globals": {
|
|
4655
|
-
severity: "off",
|
|
4656
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4657
|
-
},
|
|
4658
|
-
"jest/no-mocks-import": {
|
|
4659
|
-
severity: "off",
|
|
4660
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4661
|
-
},
|
|
4662
|
-
"jest/no-standalone-expect": {
|
|
4663
|
-
severity: "off",
|
|
4664
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4665
|
-
},
|
|
4666
|
-
"jest/no-test-prefixes": {
|
|
4667
|
-
severity: "off",
|
|
4668
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4669
|
-
},
|
|
4670
|
-
"jest/prefer-to-be": {
|
|
4671
|
-
severity: "off",
|
|
4672
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4673
|
-
},
|
|
4674
|
-
"jest/prefer-to-contain": {
|
|
4675
|
-
severity: "off",
|
|
4676
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4677
|
-
},
|
|
4678
|
-
"jest/prefer-to-have-length": {
|
|
4679
|
-
severity: "off",
|
|
4680
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4681
|
-
},
|
|
4682
|
-
"jest/valid-describe-callback": {
|
|
4683
|
-
severity: "off",
|
|
4684
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4685
|
-
},
|
|
4686
|
-
"jest/valid-expect": {
|
|
4687
|
-
severity: "off",
|
|
4688
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4689
|
-
},
|
|
4690
|
-
"jest/valid-expect-in-promise": {
|
|
4691
|
-
severity: "off",
|
|
4692
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4693
|
-
},
|
|
4694
|
-
"jest/valid-title": {
|
|
4695
|
-
severity: "off",
|
|
4696
|
-
reason: "pre-existing test-suite debt; enabling it on adoption would surface a wall of findings and make a lateral move look like a regression"
|
|
4697
|
-
},
|
|
4698
|
-
"jsx-a11y/alt-text": "error",
|
|
4699
|
-
"jsx-a11y/anchor-has-content": "error",
|
|
4700
|
-
"jsx-a11y/anchor-is-valid": "error",
|
|
4701
|
-
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
|
|
4702
|
-
"jsx-a11y/aria-props": "error",
|
|
4703
|
-
"jsx-a11y/aria-proptypes": "error",
|
|
4704
|
-
"jsx-a11y/aria-role": "error",
|
|
4705
|
-
"jsx-a11y/aria-unsupported-elements": "error",
|
|
4706
|
-
"jsx-a11y/autocomplete-valid": "error",
|
|
4707
|
-
"jsx-a11y/click-events-have-key-events": "error",
|
|
4708
|
-
"jsx-a11y/heading-has-content": "error",
|
|
4709
|
-
"jsx-a11y/html-has-lang": "error",
|
|
4710
|
-
"jsx-a11y/iframe-has-title": "error",
|
|
4711
|
-
"jsx-a11y/img-redundant-alt": {
|
|
4712
|
-
severity: "off",
|
|
4713
|
-
reason: 'one real finding, a decorative image whose title is already rendered as a heading beside it, so the fix is alt="". A genuine accessibility issue rather than a false positive: parked only so swapping linters stays a lateral move, and worth switching back on as soon as it is fixed'
|
|
4714
|
-
},
|
|
4715
|
-
"jsx-a11y/interactive-supports-focus": [
|
|
4716
|
-
"error",
|
|
4717
|
-
{
|
|
4718
|
-
tabbable: [
|
|
4719
|
-
"button",
|
|
4720
|
-
"checkbox",
|
|
4721
|
-
"link",
|
|
4722
|
-
"progressbar",
|
|
4723
|
-
"searchbox",
|
|
4724
|
-
"slider",
|
|
4725
|
-
"spinbutton",
|
|
4726
|
-
"switch",
|
|
4727
|
-
"textbox"
|
|
4728
|
-
]
|
|
4729
|
-
}
|
|
4730
|
-
],
|
|
4731
|
-
"jsx-a11y/label-has-associated-control": "error",
|
|
4732
|
-
"jsx-a11y/media-has-caption": "error",
|
|
4733
|
-
"jsx-a11y/mouse-events-have-key-events": "error",
|
|
4734
|
-
"jsx-a11y/no-access-key": "error",
|
|
4735
|
-
"jsx-a11y/no-autofocus": "error",
|
|
4736
|
-
"jsx-a11y/no-distracting-elements": "error",
|
|
4737
|
-
"jsx-a11y/no-interactive-element-to-noninteractive-role": "error",
|
|
4738
|
-
"jsx-a11y/no-noninteractive-element-interactions": [
|
|
4739
|
-
"error",
|
|
4740
|
-
{
|
|
4741
|
-
body: ["onError", "onLoad"],
|
|
4742
|
-
iframe: ["onError", "onLoad"],
|
|
4743
|
-
img: ["onError", "onLoad"]
|
|
4744
|
-
}
|
|
4745
|
-
],
|
|
4746
|
-
"jsx-a11y/no-noninteractive-element-to-interactive-role": "error",
|
|
4747
|
-
"jsx-a11y/no-noninteractive-tabindex": "error",
|
|
4748
|
-
"jsx-a11y/no-redundant-roles": "error",
|
|
4749
|
-
"jsx-a11y/no-static-element-interactions": "error",
|
|
4750
|
-
"jsx-a11y/role-has-required-aria-props": "error",
|
|
4751
|
-
"jsx-a11y/role-supports-aria-props": "error",
|
|
4752
|
-
"jsx-a11y/scope": "error",
|
|
4753
|
-
"jsx-a11y/tabindex-no-positive": "error",
|
|
4754
|
-
"no-async-promise-executor": "error",
|
|
4755
|
-
"no-barrel-files/no-barrel-files": {
|
|
4756
|
-
severity: "warn",
|
|
4757
|
-
reason: "the modules already ran this at warn (confirmed in the host-admin proof-of-concept config); nest disables it outright as deliberate architecture, react keeps it visible"
|
|
4758
|
-
},
|
|
4759
|
-
"no-case-declarations": "error",
|
|
4760
|
-
"no-compare-neg-zero": "error",
|
|
4761
|
-
"no-cond-assign": ["error", "except-parens"],
|
|
4762
|
-
"no-console": {
|
|
4763
|
-
severity: "off",
|
|
4764
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
4765
|
-
},
|
|
4766
|
-
"no-constant-binary-expression": "error",
|
|
4767
|
-
"no-constant-condition": [
|
|
4768
|
-
"error",
|
|
4769
|
-
{
|
|
4770
|
-
checkLoops: "allExceptWhileTrue"
|
|
4771
|
-
}
|
|
4772
|
-
],
|
|
4773
|
-
"no-control-regex": "error",
|
|
4774
|
-
"no-debugger": "error",
|
|
4775
|
-
"no-delete-var": "error",
|
|
4776
|
-
"no-dupe-else-if": "error",
|
|
4777
|
-
"no-duplicate-case": "error",
|
|
4778
|
-
"no-empty": [
|
|
4779
|
-
"error",
|
|
4780
|
-
{
|
|
4781
|
-
allowEmptyCatch: false
|
|
4782
|
-
}
|
|
4783
|
-
],
|
|
4784
|
-
"no-empty-character-class": "error",
|
|
4785
|
-
"no-empty-pattern": [
|
|
4786
|
-
"error",
|
|
4787
|
-
{
|
|
4788
|
-
allowObjectPatternsAsParameters: false
|
|
4789
|
-
}
|
|
4790
|
-
],
|
|
4791
|
-
"no-empty-static-block": "error",
|
|
4792
|
-
"no-ex-assign": "error",
|
|
4793
|
-
"no-extra-boolean-cast": ["error", {}],
|
|
4794
|
-
"no-fallthrough": [
|
|
4795
|
-
"error",
|
|
4796
|
-
{
|
|
4797
|
-
allowEmptyCase: false,
|
|
4798
|
-
reportUnusedFallthroughComment: false
|
|
4799
|
-
}
|
|
4800
|
-
],
|
|
4801
|
-
"no-global-assign": [
|
|
4802
|
-
"error",
|
|
4803
|
-
{
|
|
4804
|
-
exceptions: []
|
|
4805
|
-
}
|
|
4806
|
-
],
|
|
4807
|
-
"no-invalid-regexp": ["error", {}],
|
|
4808
|
-
"no-irregular-whitespace": [
|
|
4809
|
-
"error",
|
|
4810
|
-
{
|
|
4811
|
-
skipComments: false,
|
|
4812
|
-
skipJSXText: false,
|
|
4813
|
-
skipRegExps: false,
|
|
4814
|
-
skipStrings: true,
|
|
4815
|
-
skipTemplates: false
|
|
4816
|
-
}
|
|
4817
|
-
],
|
|
4818
|
-
"no-loss-of-precision": "error",
|
|
4819
|
-
"no-misleading-character-class": "error",
|
|
4820
|
-
"no-nonoctal-decimal-escape": "error",
|
|
4821
|
-
"no-prototype-builtins": "error",
|
|
4822
|
-
"no-regex-spaces": "error",
|
|
4823
|
-
"no-restricted-imports": [
|
|
4824
|
-
"error",
|
|
4825
|
-
{
|
|
4826
|
-
patterns: [
|
|
4827
|
-
{
|
|
4828
|
-
group: ["next/*"],
|
|
4829
|
-
message: "Importing from next/* is not allowed in the admin project."
|
|
4830
|
-
},
|
|
4831
|
-
{
|
|
4832
|
-
group: ["storybook/*"],
|
|
4833
|
-
message: "Importing from storybook/* is not allowed in the admin project."
|
|
4834
|
-
},
|
|
4835
|
-
{
|
|
4836
|
-
group: ["@nestjs/*"],
|
|
4837
|
-
message: "Importing from @nestjs/* is not allowed in the admin project."
|
|
4838
|
-
},
|
|
4839
|
-
{
|
|
4840
|
-
group: ["next-i18next"],
|
|
4841
|
-
message: "Importing from next-i18next is not allowed in the admin project."
|
|
4842
|
-
},
|
|
4843
|
-
{
|
|
4844
|
-
group: ["@hublo/style/colors", "@hublo/style/colors/*"],
|
|
4845
|
-
message: "Importing runtime colors directly is not allowed. Use the MUI theme, theme-derived CSS variables, or an explicit product-specific mapping."
|
|
4846
|
-
}
|
|
4847
|
-
]
|
|
4848
|
-
}
|
|
4849
|
-
],
|
|
4850
|
-
"no-self-assign": [
|
|
4851
|
-
"error",
|
|
4852
|
-
{
|
|
4853
|
-
props: true
|
|
4854
|
-
}
|
|
4855
|
-
],
|
|
4856
|
-
"no-shadow-restricted-names": [
|
|
4857
|
-
"error",
|
|
4858
|
-
{
|
|
4859
|
-
reportGlobalThis: false
|
|
4860
|
-
}
|
|
4861
|
-
],
|
|
4862
|
-
"no-sparse-arrays": "error",
|
|
4863
|
-
"no-unexpected-multiline": "error",
|
|
4864
|
-
"no-unsafe-finally": "error",
|
|
4865
|
-
"no-unsafe-optional-chaining": {
|
|
4866
|
-
severity: "off",
|
|
4867
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
4868
|
-
},
|
|
4869
|
-
"no-unused-labels": "error",
|
|
4870
|
-
"no-unused-private-class-members": "error",
|
|
4871
|
-
"no-useless-backreference": "error",
|
|
4872
|
-
"no-useless-catch": "error",
|
|
4873
|
-
"no-useless-escape": [
|
|
4874
|
-
"error",
|
|
4875
|
-
{
|
|
4876
|
-
allowRegexCharacters: []
|
|
4877
|
-
}
|
|
4878
|
-
],
|
|
4879
|
-
"nx/enforce-module-boundaries": [
|
|
4880
|
-
"error",
|
|
4881
|
-
{
|
|
4882
|
-
enforceBuildableLibDependency: true,
|
|
4883
|
-
allow: [],
|
|
4884
|
-
depConstraints: [
|
|
4885
|
-
{
|
|
4886
|
-
sourceTag: "*",
|
|
4887
|
-
onlyDependOnLibsWithTags: ["*"]
|
|
4888
|
-
}
|
|
4889
|
-
]
|
|
4890
|
-
}
|
|
4891
|
-
],
|
|
4892
|
-
"react-hooks/exhaustive-deps": {
|
|
4893
|
-
severity: "warn",
|
|
4894
|
-
reason: "the modules already ran this at warn (confirmed in the host-admin proof-of-concept config); its suggested fix can change behaviour, so it reports and a human decides"
|
|
4895
|
-
},
|
|
4896
|
-
"react-hooks/rules-of-hooks": "error",
|
|
4897
|
-
"react-refresh/only-export-components": {
|
|
4898
|
-
severity: "warn",
|
|
4899
|
-
reason: "the modules already ran this at warn (confirmed in the host-admin proof-of-concept config); it guards fast-refresh ergonomics, not correctness",
|
|
4900
|
-
options: [
|
|
4901
|
-
{
|
|
4902
|
-
allowConstantExport: true
|
|
4903
|
-
}
|
|
4904
|
-
]
|
|
4905
|
-
},
|
|
4906
|
-
"react/jsx-curly-brace-presence": {
|
|
4907
|
-
severity: "off",
|
|
4908
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
4909
|
-
},
|
|
4910
|
-
"require-yield": "error",
|
|
4911
|
-
"styled-components-a11y/alt-text": "error",
|
|
4912
|
-
"styled-components-a11y/anchor-has-content": "error",
|
|
4913
|
-
"styled-components-a11y/anchor-is-valid": "error",
|
|
4914
|
-
"styled-components-a11y/aria-activedescendant-has-tabindex": "error",
|
|
4915
|
-
"styled-components-a11y/aria-props": "error",
|
|
4916
|
-
"styled-components-a11y/aria-proptypes": "error",
|
|
4917
|
-
"styled-components-a11y/aria-role": "error",
|
|
4918
|
-
"styled-components-a11y/aria-unsupported-elements": "error",
|
|
4919
|
-
"styled-components-a11y/autocomplete-valid": "error",
|
|
4920
|
-
"styled-components-a11y/click-events-have-key-events": "error",
|
|
4921
|
-
"styled-components-a11y/control-has-associated-label": {
|
|
4922
|
-
severity: "off",
|
|
4923
|
-
reason: "off in the host-admin proof-of-concept config, with its element and role ignore lists; it fires on composed styled components where the label lives in a wrapper the rule cannot see",
|
|
4924
|
-
options: [
|
|
4925
|
-
{
|
|
4926
|
-
ignoreElements: ["audio", "canvas", "embed", "input", "textarea", "tr", "video"],
|
|
4927
|
-
ignoreRoles: [
|
|
4928
|
-
"grid",
|
|
4929
|
-
"listbox",
|
|
4930
|
-
"menu",
|
|
4931
|
-
"menubar",
|
|
4932
|
-
"radiogroup",
|
|
4933
|
-
"row",
|
|
4934
|
-
"tablist",
|
|
4935
|
-
"toolbar",
|
|
4936
|
-
"tree",
|
|
4937
|
-
"treegrid"
|
|
4938
|
-
],
|
|
4939
|
-
includeRoles: ["alert", "dialog"]
|
|
4940
|
-
}
|
|
4941
|
-
]
|
|
4942
|
-
},
|
|
4943
|
-
"styled-components-a11y/heading-has-content": "error",
|
|
4944
|
-
"styled-components-a11y/html-has-lang": "error",
|
|
4945
|
-
"styled-components-a11y/iframe-has-title": "error",
|
|
4946
|
-
"styled-components-a11y/img-redundant-alt": "error",
|
|
4947
|
-
"styled-components-a11y/interactive-supports-focus": [
|
|
4948
|
-
"error",
|
|
4949
|
-
{
|
|
4950
|
-
tabbable: [
|
|
4951
|
-
"button",
|
|
4952
|
-
"checkbox",
|
|
4953
|
-
"link",
|
|
4954
|
-
"progressbar",
|
|
4955
|
-
"searchbox",
|
|
4956
|
-
"slider",
|
|
4957
|
-
"spinbutton",
|
|
4958
|
-
"switch",
|
|
4959
|
-
"textbox"
|
|
4960
|
-
]
|
|
4961
|
-
}
|
|
4962
|
-
],
|
|
4963
|
-
"styled-components-a11y/label-has-associated-control": "error",
|
|
4964
|
-
"styled-components-a11y/label-has-for": {
|
|
4965
|
-
severity: "off",
|
|
4966
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
4967
|
-
},
|
|
4968
|
-
"styled-components-a11y/media-has-caption": "error",
|
|
4969
|
-
"styled-components-a11y/mouse-events-have-key-events": "error",
|
|
4970
|
-
"styled-components-a11y/no-access-key": "error",
|
|
4971
|
-
"styled-components-a11y/no-autofocus": "error",
|
|
4972
|
-
"styled-components-a11y/no-distracting-elements": "error",
|
|
4973
|
-
"styled-components-a11y/no-interactive-element-to-noninteractive-role": "error",
|
|
4974
|
-
"styled-components-a11y/no-noninteractive-element-interactions": [
|
|
4975
|
-
"error",
|
|
4976
|
-
{
|
|
4977
|
-
body: ["onError", "onLoad"],
|
|
4978
|
-
iframe: ["onError", "onLoad"],
|
|
4979
|
-
img: ["onError", "onLoad"]
|
|
4980
|
-
}
|
|
4981
|
-
],
|
|
4982
|
-
"styled-components-a11y/no-noninteractive-element-to-interactive-role": "error",
|
|
4983
|
-
"styled-components-a11y/no-noninteractive-tabindex": "error",
|
|
4984
|
-
"styled-components-a11y/no-redundant-roles": "error",
|
|
4985
|
-
"styled-components-a11y/no-static-element-interactions": "error",
|
|
4986
|
-
"styled-components-a11y/role-has-required-aria-props": "error",
|
|
4987
|
-
"styled-components-a11y/role-supports-aria-props": "error",
|
|
4988
|
-
"styled-components-a11y/scope": "error",
|
|
4989
|
-
"styled-components-a11y/tabindex-no-positive": "error",
|
|
4990
|
-
"typescript/await-thenable": "error",
|
|
4991
|
-
"typescript/no-array-delete": "error",
|
|
4992
|
-
"typescript/no-base-to-string": "error",
|
|
4993
|
-
"typescript/no-duplicate-type-constituents": "error",
|
|
4994
|
-
"typescript/no-empty-function": {
|
|
4995
|
-
severity: "off",
|
|
4996
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
4997
|
-
},
|
|
4998
|
-
"typescript/no-explicit-any": {
|
|
4999
|
-
severity: "off",
|
|
5000
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5001
|
-
},
|
|
5002
|
-
"typescript/no-floating-promises": [
|
|
5003
|
-
"error",
|
|
5004
|
-
{
|
|
5005
|
-
ignoreVoid: true
|
|
5006
|
-
}
|
|
5007
|
-
],
|
|
5008
|
-
"typescript/no-for-in-array": "error",
|
|
5009
|
-
"typescript/no-implied-eval": "error",
|
|
5010
|
-
"typescript/no-inferrable-types": "error",
|
|
5011
|
-
"typescript/no-misused-promises": [
|
|
5012
|
-
"error",
|
|
5013
|
-
{
|
|
5014
|
-
checksVoidReturn: {
|
|
5015
|
-
attributes: false
|
|
5016
|
-
}
|
|
5017
|
-
}
|
|
5018
|
-
],
|
|
5019
|
-
"typescript/no-non-null-assertion": {
|
|
5020
|
-
severity: "warn",
|
|
5021
|
-
reason: "kept at the severity the proof of concept measured; no module config set it, so raising it to error would be a NEW enforcement decision rather than a like-for-like migration, and it needs its own count of violations first"
|
|
5022
|
-
},
|
|
5023
|
-
"typescript/no-redundant-type-constituents": "error",
|
|
5024
|
-
"typescript/no-require-imports": "error",
|
|
5025
|
-
"typescript/no-unnecessary-type-assertion": {
|
|
5026
|
-
severity: "off",
|
|
5027
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5028
|
-
},
|
|
5029
|
-
"typescript/no-unsafe-argument": {
|
|
5030
|
-
severity: "off",
|
|
5031
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5032
|
-
},
|
|
5033
|
-
"typescript/no-unsafe-assignment": {
|
|
5034
|
-
severity: "off",
|
|
5035
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5036
|
-
},
|
|
5037
|
-
"typescript/no-unsafe-call": {
|
|
5038
|
-
severity: "off",
|
|
5039
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5040
|
-
},
|
|
5041
|
-
"typescript/no-unsafe-enum-comparison": {
|
|
5042
|
-
severity: "off",
|
|
5043
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5044
|
-
},
|
|
5045
|
-
"typescript/no-unsafe-member-access": {
|
|
5046
|
-
severity: "off",
|
|
5047
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5048
|
-
},
|
|
5049
|
-
"typescript/no-unsafe-return": {
|
|
5050
|
-
severity: "off",
|
|
5051
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5052
|
-
},
|
|
5053
|
-
"typescript/no-unsafe-unary-minus": "error",
|
|
5054
|
-
"typescript/no-unused-vars": {
|
|
5055
|
-
severity: "off",
|
|
5056
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5057
|
-
},
|
|
5058
|
-
"typescript/only-throw-error": {
|
|
5059
|
-
severity: "off",
|
|
5060
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5061
|
-
},
|
|
5062
|
-
"typescript/prefer-promise-reject-errors": "error",
|
|
5063
|
-
"typescript/require-await": {
|
|
5064
|
-
severity: "off",
|
|
5065
|
-
reason: "pre-existing debt measured during the proof of concept; parked so adoption stays non-breaking"
|
|
5066
|
-
},
|
|
5067
|
-
"typescript/restrict-plus-operands": "error",
|
|
5068
|
-
"typescript/restrict-template-expressions": "error",
|
|
5069
|
-
"typescript/return-await": {
|
|
5070
|
-
severity: "warn",
|
|
5071
|
-
reason: "replaces the deprecated core `no-return-await`, which both modules set to error but which was never actually reporting: the nx lint target expanded to 2 files of 2888. `in-try-catch` rather than `never`, and the planning adoption is what settled it. `never` forces `return await f()` to become `const x = await f(); return x` even inside a `try`, where the await is REQUIRED for the catch to fire: it produced 10 such edits across 15 modules, every one of them inside a try/catch, and every one of them a rewrite that made the code longer without making it safer. Worse, the obvious reading of the rule is to delete the `await`, which silently stops the catch from running. `in-try-catch` is what typescript-eslint recommends and flags none of those 10. Held at warn so adoption does not turn a green module red, and raised to error once the remaining findings are fixed.",
|
|
5072
|
-
options: ["in-try-catch"]
|
|
5073
|
-
},
|
|
5074
|
-
"typescript/switch-exhaustiveness-check": {
|
|
5075
|
-
severity: "warn",
|
|
5076
|
-
reason: "kept at the severity the proof of concept measured; no module config set it, so raising it to error would be a NEW enforcement decision rather than a like-for-like migration, and it needs its own count of violations first"
|
|
5077
|
-
},
|
|
5078
|
-
"typescript/unbound-method": "error",
|
|
5079
|
-
"use-isnan": [
|
|
5080
|
-
"error",
|
|
5081
|
-
{
|
|
5082
|
-
enforceForIndexOf: false,
|
|
5083
|
-
enforceForSwitchCase: true
|
|
5084
|
-
}
|
|
5085
|
-
],
|
|
5086
|
-
"valid-typeof": [
|
|
5087
|
-
"error",
|
|
5088
|
-
{
|
|
5089
|
-
requireStringLiterals: false
|
|
5090
|
-
}
|
|
5091
|
-
],
|
|
5092
|
-
"vitest/expect-expect": {
|
|
5093
|
-
severity: "warn",
|
|
5094
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5095
|
-
},
|
|
5096
|
-
"vitest/no-alias-methods": {
|
|
5097
|
-
severity: "warn",
|
|
5098
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5099
|
-
},
|
|
5100
|
-
"vitest/no-commented-out-tests": {
|
|
5101
|
-
severity: "warn",
|
|
5102
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5103
|
-
},
|
|
5104
|
-
"vitest/no-conditional-expect": {
|
|
5105
|
-
severity: "warn",
|
|
5106
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5107
|
-
},
|
|
5108
|
-
"vitest/no-disabled-tests": {
|
|
5109
|
-
severity: "warn",
|
|
5110
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5111
|
-
},
|
|
5112
|
-
"vitest/no-focused-tests": {
|
|
5113
|
-
severity: "warn",
|
|
5114
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5115
|
-
},
|
|
5116
|
-
"vitest/no-identical-title": {
|
|
5117
|
-
severity: "warn",
|
|
5118
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5119
|
-
},
|
|
5120
|
-
"vitest/no-interpolation-in-snapshots": {
|
|
5121
|
-
severity: "warn",
|
|
5122
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5123
|
-
},
|
|
5124
|
-
"vitest/no-mocks-import": {
|
|
5125
|
-
severity: "warn",
|
|
5126
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5127
|
-
},
|
|
5128
|
-
"vitest/no-standalone-expect": {
|
|
5129
|
-
severity: "warn",
|
|
5130
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5131
|
-
},
|
|
5132
|
-
"vitest/no-test-prefixes": {
|
|
5133
|
-
severity: "warn",
|
|
5134
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5135
|
-
},
|
|
5136
|
-
"vitest/prefer-to-be": {
|
|
5137
|
-
severity: "warn",
|
|
5138
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5139
|
-
},
|
|
5140
|
-
"vitest/prefer-to-contain": {
|
|
5141
|
-
severity: "warn",
|
|
5142
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5143
|
-
},
|
|
5144
|
-
"vitest/prefer-to-have-length": {
|
|
5145
|
-
severity: "warn",
|
|
5146
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5147
|
-
},
|
|
5148
|
-
"vitest/require-mock-type-parameters": {
|
|
5149
|
-
severity: "off",
|
|
5150
|
-
reason: "4 479 of the 5 255 findings this plugin reports over this repository, 85% of them. It asks for type parameters on vi.fn<\u2026>(), a convention this codebase never had; adopting it is its own piece of work and not part of reading the right plugin"
|
|
5151
|
-
},
|
|
5152
|
-
"vitest/require-to-throw-message": {
|
|
5153
|
-
severity: "warn",
|
|
5154
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5155
|
-
},
|
|
5156
|
-
"vitest/valid-describe-callback": {
|
|
5157
|
-
severity: "warn",
|
|
5158
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5159
|
-
},
|
|
5160
|
-
"vitest/valid-expect": {
|
|
5161
|
-
severity: "warn",
|
|
5162
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5163
|
-
},
|
|
5164
|
-
"vitest/valid-expect-in-promise": {
|
|
5165
|
-
severity: "warn",
|
|
5166
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5167
|
-
},
|
|
5168
|
-
"vitest/valid-title": {
|
|
5169
|
-
severity: "warn",
|
|
5170
|
-
reason: "new to this preset and the test suite predates it, so it reports and never blocks. The reason the jest equivalent was parked was that enabling it on adoption would make a lateral move look like a regression; a warning does not"
|
|
5171
|
-
},
|
|
5172
|
-
"vitest/warn-todo": {
|
|
5173
|
-
severity: "warn",
|
|
5174
|
-
reason: "a todo test is a reminder rather than a defect, so it reports and never blocks"
|
|
5175
|
-
}
|
|
5176
|
-
},
|
|
5177
|
-
uncovered: {
|
|
5178
|
-
"import/order": "import ordering is FORMATTING, and the format role owns it: oxfmt's `sortImports` reproduces exactly these groups (builtin, external, internal, parent/index, sibling, alphabetical, blank line between) and sorts a file completely in ONE pass, because it rewrites the whole import block. A lint fixer cannot: it emits text edits over overlapping ranges, so this rule needed several runs to finish (five imports took four passes, measured) and sentinel deliberately runs autofix once. Enforced by `pnpm run format`, not by the linter, which is also why `eslint-plugin-import` is no longer hosted at all: its only other rule, no-duplicates, is native in oxlint.",
|
|
5179
|
-
"no-octal": "no oxlint equivalent",
|
|
5180
|
-
"no-restricted-syntax": "no oxlint equivalent as configuration, so the AST selectors this repo used are shipped as real rules in the local `hublo` plugin instead, which this tier hosts (`../plugins/hublo.js`). Three are hosted today: the eight palette selectors as `hublo/no-palette-common`, the lookbehind selector as `hublo/no-regex-lookbehind`, and the TanStack Router one as `hublo/require-reload-document`, carried here from an ESLint selector in the monorepo (PR #22043) because ADR 0042 makes this the layer that outlives it. App tier only: measured on main, `libs/front` calls `redirect(` nowhere, while host-admin does in 93 files and console in 2. Any selector NOT in that plugin is not enforced here; propose it and it joins the plugin rather than a per-module copy.",
|
|
5181
|
-
semi: "formatting, and the formatter owns it. It moves to oxfmt, which is deliberately the LAST step of the migration, so nothing enforces it in between."
|
|
5182
|
-
},
|
|
5183
|
-
overrides: [
|
|
5184
|
-
{
|
|
5185
|
-
files: [
|
|
5186
|
-
"**/*.test.ts",
|
|
5187
|
-
"**/*.test.tsx",
|
|
5188
|
-
"**/*.spec.ts",
|
|
5189
|
-
"**/*.spec.tsx",
|
|
5190
|
-
"**/*.integration-spec.ts",
|
|
5191
|
-
"**/*.e2e-spec.ts"
|
|
5192
|
-
],
|
|
5193
|
-
rules: {
|
|
5194
|
-
"no-restricted-properties": {
|
|
5195
|
-
severity: "warn",
|
|
5196
|
-
reason: "held at warn: over the 8 011 test files, 7 call Math.random(), 104 call Date.now(), 3 crypto.randomUUID(), 1 performance.now() and 1 process.hrtime, and 28 of the files that read the clock already install fake timers. A warning says it without turning a suite that was green yesterday red. Verified at error on a fixture carrying all nine forms: these six are reported, new Date('2026-01-01') is not, which is the point",
|
|
5197
|
-
options: [
|
|
5198
|
-
{
|
|
5199
|
-
object: "Math",
|
|
5200
|
-
property: "random",
|
|
5201
|
-
message: "No Math.random() in a test: use a deterministic fixture, or stub the random source."
|
|
5202
|
-
},
|
|
5203
|
-
{
|
|
5204
|
-
object: "Date",
|
|
5205
|
-
property: "now",
|
|
5206
|
-
message: "No Date.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
5207
|
-
},
|
|
5208
|
-
{
|
|
5209
|
-
object: "performance",
|
|
5210
|
-
property: "now",
|
|
5211
|
-
message: "No performance.now() in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
5212
|
-
},
|
|
5213
|
-
{
|
|
5214
|
-
object: "process",
|
|
5215
|
-
property: "hrtime",
|
|
5216
|
-
message: "No process.hrtime in a test: use vi.useFakeTimers() with vi.setSystemTime()."
|
|
5217
|
-
},
|
|
5218
|
-
{
|
|
5219
|
-
object: "crypto",
|
|
5220
|
-
property: "randomUUID",
|
|
5221
|
-
message: "No crypto.randomUUID() in a test: use a fixed id, or stub the random source."
|
|
5222
|
-
},
|
|
5223
|
-
{
|
|
5224
|
-
object: "crypto",
|
|
5225
|
-
property: "getRandomValues",
|
|
5226
|
-
message: "No crypto.getRandomValues() in a test: use a fixed buffer, or stub the random source."
|
|
5227
|
-
}
|
|
5228
|
-
]
|
|
5229
|
-
},
|
|
5230
|
-
"no-restricted-globals": {
|
|
5231
|
-
severity: "warn",
|
|
5232
|
-
reason: "held at warn: 68 test files call setTimeout and only 2 of them install fake timers, so waiting on the real clock is the second source of flakiness after reading it. The flush idiom await new Promise((resolve) => setTimeout(resolve, 0)) is inside that count and is usually harmless, which is exactly why this reports and never blocks",
|
|
5233
|
-
options: [
|
|
5234
|
-
{
|
|
5235
|
-
name: "setTimeout",
|
|
5236
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
5237
|
-
},
|
|
5238
|
-
{
|
|
5239
|
-
name: "setInterval",
|
|
5240
|
-
message: "No real timer in a test: vi.useFakeTimers() then vi.advanceTimersByTime()."
|
|
5241
|
-
}
|
|
5242
|
-
]
|
|
5243
|
-
}
|
|
5244
|
-
}
|
|
3259
|
+
* The dedicated `format` / `format:fix` scripts stay, for running the formatter alone.
|
|
3260
|
+
*/
|
|
3261
|
+
joinFormatIntoLint(original, rewritten, selfCommand2) {
|
|
3262
|
+
const command = selfCommand2 ?? SENTINEL_FORMAT_COMMAND;
|
|
3263
|
+
for (const [name, keepFix] of [
|
|
3264
|
+
["lint", false],
|
|
3265
|
+
["lint:fix", true]
|
|
3266
|
+
]) {
|
|
3267
|
+
const script = rewritten[name] ?? original[name];
|
|
3268
|
+
if (!script || script.trim() === "") continue;
|
|
3269
|
+
if (invokesFormat(script)) continue;
|
|
3270
|
+
rewritten[name] = `${script} && ${keepFix ? `${command} --fix` : command}`;
|
|
5245
3271
|
}
|
|
5246
|
-
|
|
5247
|
-
};
|
|
5248
|
-
|
|
5249
|
-
// src/roles/lint/presets/shared.json
|
|
5250
|
-
var shared_default2 = {
|
|
5251
|
-
rules: {
|
|
5252
|
-
"no-var": "error",
|
|
5253
|
-
"prefer-const": [
|
|
5254
|
-
"error",
|
|
5255
|
-
{
|
|
5256
|
-
destructuring: "any",
|
|
5257
|
-
ignoreReadBeforeAssign: false
|
|
5258
|
-
}
|
|
5259
|
-
],
|
|
5260
|
-
"prefer-rest-params": "error",
|
|
5261
|
-
"prefer-spread": "error",
|
|
5262
|
-
"typescript/ban-ts-comment": "error",
|
|
5263
|
-
"typescript/no-array-constructor": "error",
|
|
5264
|
-
"typescript/no-duplicate-enum-values": "error",
|
|
5265
|
-
"typescript/no-empty-object-type": "error",
|
|
5266
|
-
"typescript/no-extra-non-null-assertion": "error",
|
|
5267
|
-
"typescript/no-misused-new": "error",
|
|
5268
|
-
"typescript/no-namespace": "error",
|
|
5269
|
-
"typescript/no-non-null-asserted-optional-chain": "error",
|
|
5270
|
-
"typescript/no-this-alias": "error",
|
|
5271
|
-
"typescript/no-unnecessary-type-constraint": "error",
|
|
5272
|
-
"typescript/no-unsafe-declaration-merging": "error",
|
|
5273
|
-
"typescript/no-unsafe-function-type": "error",
|
|
5274
|
-
"typescript/no-unused-expressions": [
|
|
5275
|
-
"error",
|
|
5276
|
-
{
|
|
5277
|
-
allowShortCircuit: false,
|
|
5278
|
-
allowTaggedTemplates: false,
|
|
5279
|
-
allowTernary: false
|
|
5280
|
-
}
|
|
5281
|
-
],
|
|
5282
|
-
"typescript/no-wrapper-object-types": "error",
|
|
5283
|
-
"typescript/prefer-as-const": "error",
|
|
5284
|
-
"typescript/prefer-namespace-keyword": "error",
|
|
5285
|
-
"typescript/triple-slash-reference": "error"
|
|
3272
|
+
return rewritten;
|
|
5286
3273
|
}
|
|
5287
3274
|
};
|
|
5288
3275
|
|
|
5289
|
-
// src/roles/
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
rules: {
|
|
5295
|
-
"constructor-super": "error",
|
|
5296
|
-
"for-direction": "error",
|
|
5297
|
-
"getter-return": [
|
|
5298
|
-
"error",
|
|
5299
|
-
{
|
|
5300
|
-
allowImplicit: false
|
|
5301
|
-
}
|
|
5302
|
-
],
|
|
5303
|
-
"no-async-promise-executor": "error",
|
|
5304
|
-
"no-case-declarations": "error",
|
|
5305
|
-
"no-class-assign": "error",
|
|
5306
|
-
"no-compare-neg-zero": "error",
|
|
5307
|
-
"no-cond-assign": ["error", "except-parens"],
|
|
5308
|
-
"no-const-assign": "error",
|
|
5309
|
-
"no-constant-binary-expression": "error",
|
|
5310
|
-
"no-constant-condition": [
|
|
5311
|
-
"error",
|
|
5312
|
-
{
|
|
5313
|
-
checkLoops: "allExceptWhileTrue"
|
|
5314
|
-
}
|
|
5315
|
-
],
|
|
5316
|
-
"no-control-regex": "error",
|
|
5317
|
-
"no-debugger": "error",
|
|
5318
|
-
"no-delete-var": "error",
|
|
5319
|
-
"no-dupe-class-members": "error",
|
|
5320
|
-
"no-dupe-else-if": "error",
|
|
5321
|
-
"no-dupe-keys": "error",
|
|
5322
|
-
"no-duplicate-case": "error",
|
|
5323
|
-
"no-empty": [
|
|
5324
|
-
"error",
|
|
5325
|
-
{
|
|
5326
|
-
allowEmptyCatch: false
|
|
5327
|
-
}
|
|
5328
|
-
],
|
|
5329
|
-
"no-empty-character-class": "error",
|
|
5330
|
-
"no-empty-pattern": [
|
|
5331
|
-
"error",
|
|
5332
|
-
{
|
|
5333
|
-
allowObjectPatternsAsParameters: false
|
|
5334
|
-
}
|
|
5335
|
-
],
|
|
5336
|
-
"no-empty-static-block": "error",
|
|
5337
|
-
"no-ex-assign": "error",
|
|
5338
|
-
"no-extra-boolean-cast": ["error", {}],
|
|
5339
|
-
"no-fallthrough": [
|
|
5340
|
-
"error",
|
|
5341
|
-
{
|
|
5342
|
-
allowEmptyCase: false,
|
|
5343
|
-
reportUnusedFallthroughComment: false
|
|
5344
|
-
}
|
|
5345
|
-
],
|
|
5346
|
-
"no-func-assign": "error",
|
|
5347
|
-
"no-global-assign": [
|
|
5348
|
-
"error",
|
|
5349
|
-
{
|
|
5350
|
-
exceptions: []
|
|
5351
|
-
}
|
|
5352
|
-
],
|
|
5353
|
-
"no-import-assign": "error",
|
|
5354
|
-
"no-invalid-regexp": ["error", {}],
|
|
5355
|
-
"no-irregular-whitespace": [
|
|
5356
|
-
"error",
|
|
5357
|
-
{
|
|
5358
|
-
skipComments: false,
|
|
5359
|
-
skipJSXText: false,
|
|
5360
|
-
skipRegExps: false,
|
|
5361
|
-
skipStrings: true,
|
|
5362
|
-
skipTemplates: false
|
|
5363
|
-
}
|
|
5364
|
-
],
|
|
5365
|
-
"no-loss-of-precision": "error",
|
|
5366
|
-
"no-misleading-character-class": "error",
|
|
5367
|
-
"no-new-native-nonconstructor": "error",
|
|
5368
|
-
"no-nonoctal-decimal-escape": "error",
|
|
5369
|
-
"no-obj-calls": "error",
|
|
5370
|
-
"no-prototype-builtins": "error",
|
|
5371
|
-
"no-redeclare": [
|
|
5372
|
-
"error",
|
|
5373
|
-
{
|
|
5374
|
-
builtinGlobals: true
|
|
5375
|
-
}
|
|
5376
|
-
],
|
|
5377
|
-
"no-regex-spaces": "error",
|
|
5378
|
-
"no-self-assign": [
|
|
5379
|
-
"error",
|
|
5380
|
-
{
|
|
5381
|
-
props: true
|
|
5382
|
-
}
|
|
5383
|
-
],
|
|
5384
|
-
"no-setter-return": "error",
|
|
5385
|
-
"no-shadow-restricted-names": [
|
|
5386
|
-
"error",
|
|
5387
|
-
{
|
|
5388
|
-
reportGlobalThis: false
|
|
5389
|
-
}
|
|
5390
|
-
],
|
|
5391
|
-
"no-sparse-arrays": "error",
|
|
5392
|
-
"no-this-before-super": "error",
|
|
5393
|
-
"no-undef": {
|
|
5394
|
-
severity: "off",
|
|
5395
|
-
reason: "unusable under oxlint for Svelte, and not for want of configuration. Svelte 5's runes ($state, $props, $derived, $effect) are compiler globals, and `$store` auto-subscription invents an identifier per store ($_, $page, $currentAdmin, \u2026), so the names cannot be enumerated. eslint-plugin-svelte's PARSER supplies both; oxlint has no Svelte parser, so it reported 1641 undefined identifiers on hr-management, none of them real. TypeScript and svelte-check already report genuinely undefined identifiers, which is why react and nest never enabled this rule either."
|
|
5396
|
-
},
|
|
5397
|
-
"no-unreachable": "error",
|
|
5398
|
-
"no-unsafe-finally": "error",
|
|
5399
|
-
"no-unsafe-negation": [
|
|
5400
|
-
"error",
|
|
5401
|
-
{
|
|
5402
|
-
enforceForOrderingRelations: false
|
|
5403
|
-
}
|
|
5404
|
-
],
|
|
5405
|
-
"no-unsafe-optional-chaining": [
|
|
5406
|
-
"error",
|
|
5407
|
-
{
|
|
5408
|
-
disallowArithmeticOperators: false
|
|
5409
|
-
}
|
|
5410
|
-
],
|
|
5411
|
-
"no-unused-labels": "error",
|
|
5412
|
-
"no-unused-private-class-members": "error",
|
|
5413
|
-
"no-useless-backreference": "error",
|
|
5414
|
-
"no-useless-catch": "error",
|
|
5415
|
-
"no-useless-escape": [
|
|
5416
|
-
"error",
|
|
5417
|
-
{
|
|
5418
|
-
allowRegexCharacters: []
|
|
5419
|
-
}
|
|
5420
|
-
],
|
|
5421
|
-
"no-with": "error",
|
|
5422
|
-
"prefer-rest-params": {
|
|
5423
|
-
severity: "warn",
|
|
5424
|
-
reason: "error in the module's eslint config, but never actually reported: `eslint src/lib/analytics/useAnalytics.js` exits clean today while oxlint finds 3 real violations in it. Held at warn so adoption does not turn a green module red, and restored to error once they are fixed. Not auto-fixable, verified with --fix."
|
|
5425
|
-
},
|
|
5426
|
-
"prefer-spread": {
|
|
5427
|
-
severity: "warn",
|
|
5428
|
-
reason: "error in the module's eslint config, but never actually reported: `eslint src/lib/analytics/useAnalytics.js` exits clean today while oxlint finds 3 real violations in it. Held at warn so adoption does not turn a green module red, and restored to error once they are fixed. Not auto-fixable, verified with --fix."
|
|
5429
|
-
},
|
|
5430
|
-
"require-yield": "error",
|
|
5431
|
-
"typescript/no-explicit-any": {
|
|
5432
|
-
severity: "warn",
|
|
5433
|
-
reason: "libs/front/ui enforces it and apps/front/hr-management turns it off; enforcing it would newly fail hr-management, so it reports for both instead of breaking one"
|
|
5434
|
-
},
|
|
5435
|
-
"typescript/no-require-imports": "error",
|
|
5436
|
-
"typescript/no-unused-vars": {
|
|
5437
|
-
severity: "warn",
|
|
5438
|
-
reason: "the two modules disagree: libs/front/ui runs it at error with no ignore patterns, apps/front/hr-management at warn with the ^_ patterns kept here (both read from eslint --print-config). Holding it at error would newly fail hr-management, so it reports for both and keeps the patterns hr-management already relies on",
|
|
5439
|
-
options: [
|
|
5440
|
-
{
|
|
5441
|
-
varsIgnorePattern: "^_",
|
|
5442
|
-
argsIgnorePattern: "^_",
|
|
5443
|
-
destructuredArrayIgnorePattern: "^_"
|
|
5444
|
-
}
|
|
5445
|
-
]
|
|
5446
|
-
},
|
|
5447
|
-
"use-isnan": [
|
|
5448
|
-
"error",
|
|
5449
|
-
{
|
|
5450
|
-
enforceForIndexOf: false,
|
|
5451
|
-
enforceForSwitchCase: true
|
|
5452
|
-
}
|
|
5453
|
-
],
|
|
5454
|
-
"valid-typeof": [
|
|
5455
|
-
"error",
|
|
5456
|
-
{
|
|
5457
|
-
requireStringLiterals: false
|
|
5458
|
-
}
|
|
5459
|
-
]
|
|
5460
|
-
},
|
|
5461
|
-
uncovered: {
|
|
5462
|
-
"svelte/comment-directive": "oxlint cannot parse Svelte templates, so the eslint-disable comments inside markup are neither read nor honoured",
|
|
5463
|
-
"svelte/system": "the plugin internal rule that reports Svelte parse errors; it needs the Svelte parser",
|
|
5464
|
-
"svelte/no-at-debug-tags": "reads {@debug} in the template",
|
|
5465
|
-
"svelte/no-at-html-tags": "reads {@html} in the template, the XSS guard; the highest-value loss in this list",
|
|
5466
|
-
"svelte/no-dupe-else-if-blocks": "reads {#if}/{:else if} chains in the template",
|
|
5467
|
-
"svelte/no-dupe-style-properties": "reads the style block",
|
|
5468
|
-
"svelte/no-dynamic-slot-name": "reads <slot> in the template",
|
|
5469
|
-
"svelte/no-inner-declarations": "the Svelte-aware variant; the core rule it shadows is not a substitute inside markup",
|
|
5470
|
-
"svelte/no-not-function-handler": "reads on:event handlers in the template",
|
|
5471
|
-
"svelte/no-object-in-text-mustaches": "reads {expression} interpolation in the template",
|
|
5472
|
-
"svelte/no-shorthand-style-property-overrides": "reads the style block",
|
|
5473
|
-
"svelte/no-unknown-style-directive-property": "reads style: directives in the template",
|
|
5474
|
-
"svelte/no-unused-svelte-ignore": "reads svelte-ignore comments in the template",
|
|
5475
|
-
"svelte/valid-compile": "runs the Svelte compiler and reports its warnings",
|
|
5476
|
-
"no-dupe-args": "no oxlint equivalent (TypeScript rejects duplicate parameter names anyway)",
|
|
5477
|
-
"no-octal": "no oxlint equivalent"
|
|
5478
|
-
}
|
|
5479
|
-
};
|
|
3276
|
+
// src/roles/format/register.ts
|
|
3277
|
+
function registerFormat() {
|
|
3278
|
+
register(new OxfmtAdapter());
|
|
3279
|
+
setDefaultRunner("format", "oxfmt");
|
|
3280
|
+
}
|
|
5480
3281
|
|
|
5481
|
-
// src/roles/lint/
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
settings: null,
|
|
5486
|
-
rules: {
|
|
5487
|
-
"for-direction": "error",
|
|
5488
|
-
"no-async-promise-executor": "error",
|
|
5489
|
-
"no-case-declarations": "error",
|
|
5490
|
-
"no-compare-neg-zero": "error",
|
|
5491
|
-
"no-cond-assign": ["error", "except-parens"],
|
|
5492
|
-
"no-constant-binary-expression": [
|
|
5493
|
-
"error",
|
|
5494
|
-
{
|
|
5495
|
-
checkRelationalComparisons: false
|
|
5496
|
-
}
|
|
5497
|
-
],
|
|
5498
|
-
"no-constant-condition": [
|
|
5499
|
-
"error",
|
|
5500
|
-
{
|
|
5501
|
-
checkLoops: "allExceptWhileTrue"
|
|
5502
|
-
}
|
|
5503
|
-
],
|
|
5504
|
-
"no-control-regex": "error",
|
|
5505
|
-
"no-debugger": "error",
|
|
5506
|
-
"no-delete-var": "error",
|
|
5507
|
-
"no-dupe-else-if": "error",
|
|
5508
|
-
"no-duplicate-case": "error",
|
|
5509
|
-
"no-empty": [
|
|
5510
|
-
"error",
|
|
5511
|
-
{
|
|
5512
|
-
allowEmptyCatch: false
|
|
5513
|
-
}
|
|
5514
|
-
],
|
|
5515
|
-
"no-empty-character-class": "error",
|
|
5516
|
-
"no-empty-pattern": [
|
|
5517
|
-
"error",
|
|
5518
|
-
{
|
|
5519
|
-
allowObjectPatternsAsParameters: false
|
|
5520
|
-
}
|
|
5521
|
-
],
|
|
5522
|
-
"no-empty-static-block": "error",
|
|
5523
|
-
"no-ex-assign": "error",
|
|
5524
|
-
"no-extra-boolean-cast": ["error", {}],
|
|
5525
|
-
"no-fallthrough": [
|
|
5526
|
-
"error",
|
|
5527
|
-
{
|
|
5528
|
-
allowEmptyCase: false,
|
|
5529
|
-
reportUnusedFallthroughComment: false
|
|
5530
|
-
}
|
|
5531
|
-
],
|
|
5532
|
-
"no-global-assign": [
|
|
5533
|
-
"error",
|
|
5534
|
-
{
|
|
5535
|
-
exceptions: []
|
|
5536
|
-
}
|
|
5537
|
-
],
|
|
5538
|
-
"no-invalid-regexp": ["error", {}],
|
|
5539
|
-
"no-irregular-whitespace": [
|
|
5540
|
-
"error",
|
|
5541
|
-
{
|
|
5542
|
-
skipComments: false,
|
|
5543
|
-
skipJSXText: false,
|
|
5544
|
-
skipRegExps: false,
|
|
5545
|
-
skipStrings: true,
|
|
5546
|
-
skipTemplates: false
|
|
5547
|
-
}
|
|
5548
|
-
],
|
|
5549
|
-
"no-loss-of-precision": "error",
|
|
5550
|
-
"no-misleading-character-class": [
|
|
5551
|
-
"error",
|
|
5552
|
-
{
|
|
5553
|
-
allowEscape: false
|
|
5554
|
-
}
|
|
5555
|
-
],
|
|
5556
|
-
"no-nonoctal-decimal-escape": "error",
|
|
5557
|
-
"no-prototype-builtins": "error",
|
|
5558
|
-
"no-regex-spaces": "error",
|
|
5559
|
-
"no-self-assign": [
|
|
5560
|
-
"error",
|
|
5561
|
-
{
|
|
5562
|
-
props: true
|
|
5563
|
-
}
|
|
5564
|
-
],
|
|
5565
|
-
"no-shadow-restricted-names": [
|
|
5566
|
-
"error",
|
|
5567
|
-
{
|
|
5568
|
-
reportGlobalThis: true
|
|
5569
|
-
}
|
|
5570
|
-
],
|
|
5571
|
-
"no-sparse-arrays": "error",
|
|
5572
|
-
"no-unassigned-vars": "error",
|
|
5573
|
-
"no-unsafe-finally": "error",
|
|
5574
|
-
"no-unsafe-optional-chaining": [
|
|
5575
|
-
"error",
|
|
5576
|
-
{
|
|
5577
|
-
disallowArithmeticOperators: false
|
|
5578
|
-
}
|
|
5579
|
-
],
|
|
5580
|
-
"no-unused-labels": "error",
|
|
5581
|
-
"no-unused-private-class-members": "error",
|
|
5582
|
-
"no-useless-assignment": "error",
|
|
5583
|
-
"no-useless-backreference": "error",
|
|
5584
|
-
"no-useless-catch": "error",
|
|
5585
|
-
"no-useless-escape": [
|
|
5586
|
-
"error",
|
|
5587
|
-
{
|
|
5588
|
-
allowRegexCharacters: []
|
|
5589
|
-
}
|
|
5590
|
-
],
|
|
5591
|
-
"preserve-caught-error": [
|
|
5592
|
-
"error",
|
|
5593
|
-
{
|
|
5594
|
-
requireCatchParameter: false
|
|
5595
|
-
}
|
|
5596
|
-
],
|
|
5597
|
-
"require-yield": "error",
|
|
5598
|
-
"typescript/no-explicit-any": "error",
|
|
5599
|
-
"typescript/no-require-imports": "error",
|
|
5600
|
-
"typescript/no-unused-vars": [
|
|
5601
|
-
"error",
|
|
5602
|
-
{
|
|
5603
|
-
argsIgnorePattern: "^_",
|
|
5604
|
-
varsIgnorePattern: "^_"
|
|
5605
|
-
}
|
|
5606
|
-
],
|
|
5607
|
-
"use-isnan": [
|
|
5608
|
-
"error",
|
|
5609
|
-
{
|
|
5610
|
-
enforceForIndexOf: false,
|
|
5611
|
-
enforceForSwitchCase: true
|
|
5612
|
-
}
|
|
5613
|
-
],
|
|
5614
|
-
"valid-typeof": [
|
|
5615
|
-
"error",
|
|
5616
|
-
{
|
|
5617
|
-
requireStringLiterals: false
|
|
5618
|
-
}
|
|
5619
|
-
]
|
|
5620
|
-
},
|
|
5621
|
-
uncovered: {
|
|
5622
|
-
"no-octal": "no oxlint equivalent"
|
|
5623
|
-
}
|
|
5624
|
-
};
|
|
3282
|
+
// src/roles/lint/adapters/oxlint/oxlint.adapter.ts
|
|
3283
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
3284
|
+
import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3285
|
+
import { join as join21 } from "node:path";
|
|
5625
3286
|
|
|
5626
|
-
// src/
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
nest: nest_default,
|
|
5630
|
-
node: node_default,
|
|
5631
|
-
react: react_default,
|
|
5632
|
-
svelte: svelte_default,
|
|
5633
|
-
tools: tools_default
|
|
5634
|
-
};
|
|
5635
|
-
var VARIANT_FILES = {
|
|
5636
|
-
"react-lib": react_lib_default
|
|
5637
|
-
};
|
|
5638
|
-
var LINT_PRESETS = Object.keys(PRESET_FILES);
|
|
5639
|
-
var GENERATED_LINT_PRESETS = [
|
|
5640
|
-
...Object.keys(PRESET_FILES),
|
|
5641
|
-
...Object.keys(VARIANT_FILES)
|
|
5642
|
-
];
|
|
5643
|
-
function hasLintPreset(preset) {
|
|
5644
|
-
return preset in PRESET_FILES;
|
|
5645
|
-
}
|
|
5646
|
-
function presetFile(preset) {
|
|
5647
|
-
return VARIANT_FILES[preset] ?? PRESET_FILES[preset] ?? node_default;
|
|
5648
|
-
}
|
|
5649
|
-
function sharedRules() {
|
|
5650
|
-
return SHARED_RULES;
|
|
5651
|
-
}
|
|
5652
|
-
function presetRules(preset) {
|
|
5653
|
-
return presetFile(preset).rules;
|
|
5654
|
-
}
|
|
5655
|
-
function uncoveredFor(preset) {
|
|
5656
|
-
return Object.entries(presetFile(preset).uncovered ?? {}).map(([rule, reason]) => ({ rule, reason })).sort((left, right) => left.rule.localeCompare(right.rule));
|
|
3287
|
+
// src/core/config/deferred-rules.ts
|
|
3288
|
+
function deferredRuleNames(rules) {
|
|
3289
|
+
return rules.map((entry) => entry.rule);
|
|
5657
3290
|
}
|
|
5658
3291
|
|
|
5659
|
-
// src/
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
if (
|
|
5666
|
-
|
|
5667
|
-
|
|
3292
|
+
// src/core/fix-report.ts
|
|
3293
|
+
import { statSync as statSync3 } from "node:fs";
|
|
3294
|
+
import { join as join16 } from "node:path";
|
|
3295
|
+
var CONFIG_REFUSED = /failed to parse .*config|invalid config file/i;
|
|
3296
|
+
function readFailure(output) {
|
|
3297
|
+
const lines = output.split("\n").map((line2) => line2.trim());
|
|
3298
|
+
if (!lines.some((line2) => CONFIG_REFUSED.test(line2))) return void 0;
|
|
3299
|
+
const detail = lines.find((line2) => /invalid config file/i.test(line2));
|
|
3300
|
+
const line = (detail ?? lines.find((entry) => entry !== "") ?? "").replace(/^x\s*/, "");
|
|
3301
|
+
return line.split(/:\s*Failed to parse config/i)[0] ?? line;
|
|
5668
3302
|
}
|
|
5669
|
-
function
|
|
5670
|
-
|
|
5671
|
-
const
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
);
|
|
5676
|
-
}
|
|
5677
|
-
if (severity === "error") continue;
|
|
5678
|
-
const reason = isDecision(value) ? value.reason.trim() : "";
|
|
5679
|
-
if (reason === "") {
|
|
5680
|
-
throw new Error(
|
|
5681
|
-
`${preset}: rule "${rule}" is set to "${severity}" without a reason. Every rule that is not enforced must say why, so --inspect can tell a developer what is not running. Use { "severity": "${severity}", "reason": "..." }.`
|
|
5682
|
-
);
|
|
5683
|
-
}
|
|
3303
|
+
function fingerprint(path2) {
|
|
3304
|
+
try {
|
|
3305
|
+
const stat = statSync3(path2);
|
|
3306
|
+
return `${stat.size}:${stat.mtimeMs}`;
|
|
3307
|
+
} catch {
|
|
3308
|
+
return void 0;
|
|
5684
3309
|
}
|
|
5685
3310
|
}
|
|
5686
|
-
function
|
|
5687
|
-
const
|
|
5688
|
-
for (const
|
|
5689
|
-
const
|
|
5690
|
-
|
|
5691
|
-
if (other !== void 0) {
|
|
5692
|
-
throw new Error(
|
|
5693
|
-
`${label}: "${other}" and "${rule}" are the same rule to oxlint (${canonical}). Configure it once, under one name: oxlint keeps both and picks one by hash order.`
|
|
5694
|
-
);
|
|
5695
|
-
}
|
|
5696
|
-
seen.set(canonical, rule);
|
|
3311
|
+
function snapshotFiles(cwd, extensions) {
|
|
3312
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
3313
|
+
for (const file of listSourceFiles(cwd, extensions)) {
|
|
3314
|
+
const mark = fingerprint(join16(cwd, file));
|
|
3315
|
+
if (mark !== void 0) snapshot.set(file, mark);
|
|
5697
3316
|
}
|
|
3317
|
+
return snapshot;
|
|
5698
3318
|
}
|
|
5699
|
-
function
|
|
5700
|
-
const
|
|
5701
|
-
const
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
}
|
|
5706
|
-
|
|
5707
|
-
validate(label, rules);
|
|
5708
|
-
rejectTwoSpellings(label, rules);
|
|
5709
|
-
const entries = Object.entries(rules).map(([rule, value]) => {
|
|
5710
|
-
if (!isDecision(value)) return [rule, value];
|
|
5711
|
-
const options = value.options ?? [];
|
|
5712
|
-
return [rule, options.length > 0 ? [value.severity, ...options] : value.severity];
|
|
5713
|
-
});
|
|
5714
|
-
return Object.fromEntries(entries);
|
|
5715
|
-
}
|
|
5716
|
-
function rulesFor(preset) {
|
|
5717
|
-
return toRuleMap(preset, layered(preset));
|
|
5718
|
-
}
|
|
5719
|
-
function disabledFor(preset) {
|
|
5720
|
-
return decisionsAt(preset, "off");
|
|
3319
|
+
function changedSince(cwd, before, extensions) {
|
|
3320
|
+
const changed = [];
|
|
3321
|
+
for (const file of listSourceFiles(cwd, extensions)) {
|
|
3322
|
+
const now = fingerprint(join16(cwd, file));
|
|
3323
|
+
if (now === void 0) continue;
|
|
3324
|
+
if (before.get(file) !== now) changed.push(file);
|
|
3325
|
+
}
|
|
3326
|
+
return changed.sort();
|
|
5721
3327
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
3328
|
+
var NAMED_IN_REPORT = 5;
|
|
3329
|
+
var NOT_INSTALLED_YET = /invalid config file[\s\S]*node_modules/i;
|
|
3330
|
+
function presetNotInstalledYet(failure) {
|
|
3331
|
+
return NOT_INSTALLED_YET.test(failure);
|
|
5724
3332
|
}
|
|
5725
|
-
function
|
|
5726
|
-
|
|
3333
|
+
function describeFixOutcome(outcome, toolLabel) {
|
|
3334
|
+
if (outcome.failure !== void 0) {
|
|
3335
|
+
if (NOT_INSTALLED_YET.test(outcome.failure)) {
|
|
3336
|
+
return `the ${toolLabel} preset is not installed in this module yet, which is expected: this command just added it and the install comes next. Nothing was fixed. Run \`pnpm install\`, then \`sentinel --run --${toolLabel} --fix\` to clear what a machine can clear.`;
|
|
3337
|
+
}
|
|
3338
|
+
return `the ${toolLabel} autofix could not run, so nothing was fixed and this module has not been checked: ${outcome.failure}`;
|
|
3339
|
+
}
|
|
3340
|
+
if (outcome.changed.length === 0) return `the ${toolLabel} autofix changed nothing`;
|
|
3341
|
+
const named = outcome.changed.slice(0, NAMED_IN_REPORT).join(", ");
|
|
3342
|
+
const rest = outcome.changed.length - NAMED_IN_REPORT;
|
|
3343
|
+
const listed = rest > 0 ? `${named} and ${rest} more` : named;
|
|
3344
|
+
return `the ${toolLabel} autofix rewrote ${outcome.changed.length} file${outcome.changed.length === 1 ? "" : "s"}: ${listed}. Review the diff before committing: rules this module used to have switched off are enforced from now on.`;
|
|
5727
3345
|
}
|
|
5728
3346
|
|
|
5729
3347
|
// src/roles/lint/disabled-rules.ts
|
|
@@ -5773,110 +3391,6 @@ function committedExtendsList(cwd, configFile) {
|
|
|
5773
3391
|
}
|
|
5774
3392
|
}
|
|
5775
3393
|
|
|
5776
|
-
// src/roles/lint/module-own-config.ts
|
|
5777
|
-
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5778
|
-
function pluginKey(entry) {
|
|
5779
|
-
if (typeof entry === "string") return entry;
|
|
5780
|
-
if (isRecord(entry) && typeof entry.name === "string") return entry.name;
|
|
5781
|
-
if (isRecord(entry) && typeof entry.specifier === "string") return entry.specifier;
|
|
5782
|
-
return void 0;
|
|
5783
|
-
}
|
|
5784
|
-
function governedRuleNames(preset) {
|
|
5785
|
-
return /* @__PURE__ */ new Set([
|
|
5786
|
-
...Object.keys(preset.rules),
|
|
5787
|
-
...(preset.overrides ?? []).flatMap((override) => Object.keys(override.rules))
|
|
5788
|
-
]);
|
|
5789
|
-
}
|
|
5790
|
-
function governedRules(preset) {
|
|
5791
|
-
const governed = /* @__PURE__ */ new Map();
|
|
5792
|
-
for (const name of governedRuleNames(preset)) {
|
|
5793
|
-
const canonical = canonicalRuleName(name);
|
|
5794
|
-
if (!governed.has(canonical)) governed.set(canonical, name);
|
|
5795
|
-
}
|
|
5796
|
-
return governed;
|
|
5797
|
-
}
|
|
5798
|
-
function moduleOwnBlocks(committed, preset) {
|
|
5799
|
-
const blocks = {};
|
|
5800
|
-
const kept = [];
|
|
5801
|
-
const dropped = [];
|
|
5802
|
-
if (Array.isArray(committed.plugins)) {
|
|
5803
|
-
const own = committed.plugins.filter(
|
|
5804
|
-
(name) => typeof name === "string" && !preset.plugins.includes(name)
|
|
5805
|
-
);
|
|
5806
|
-
if (own.length > 0) {
|
|
5807
|
-
blocks.plugins = own;
|
|
5808
|
-
kept.push(
|
|
5809
|
-
`kept this module's own plugins (${own.join(", ")}): the preset does not enable them`
|
|
5810
|
-
);
|
|
5811
|
-
}
|
|
5812
|
-
}
|
|
5813
|
-
if (Array.isArray(committed.jsPlugins)) {
|
|
5814
|
-
const presetKeys = new Set(preset.jsPlugins.map((entry) => pluginKey(entry)));
|
|
5815
|
-
const own = [];
|
|
5816
|
-
for (const entry of committed.jsPlugins) {
|
|
5817
|
-
const key = pluginKey(entry);
|
|
5818
|
-
if (key !== void 0 && presetKeys.has(key)) dropped.push(`jsPlugins ${key}`);
|
|
5819
|
-
else own.push(entry);
|
|
5820
|
-
}
|
|
5821
|
-
if (own.length > 0) {
|
|
5822
|
-
blocks.jsPlugins = own;
|
|
5823
|
-
kept.push(
|
|
5824
|
-
`kept ${own.length} jsPlugin(s) this module added (${own.map((entry) => pluginKey(entry) ?? "?").join(", ")})`
|
|
5825
|
-
);
|
|
5826
|
-
}
|
|
5827
|
-
}
|
|
5828
|
-
if (isRecord(committed.settings)) {
|
|
5829
|
-
const presetSettings = preset.settings ?? {};
|
|
5830
|
-
const own = {};
|
|
5831
|
-
for (const [key, value] of Object.entries(committed.settings)) {
|
|
5832
|
-
if (key in presetSettings) dropped.push(`settings.${key}`);
|
|
5833
|
-
else own[key] = value;
|
|
5834
|
-
}
|
|
5835
|
-
if (Object.keys(own).length > 0) {
|
|
5836
|
-
blocks.settings = own;
|
|
5837
|
-
kept.push(`kept this module's own settings (${Object.keys(own).join(", ")})`);
|
|
5838
|
-
}
|
|
5839
|
-
}
|
|
5840
|
-
if (Array.isArray(committed.overrides)) {
|
|
5841
|
-
const governed = governedRules(preset);
|
|
5842
|
-
const byFiles = /* @__PURE__ */ new Map();
|
|
5843
|
-
for (const block of committed.overrides) {
|
|
5844
|
-
if (!isRecord(block) || !Array.isArray(block.files)) continue;
|
|
5845
|
-
const files = JSON.stringify([...block.files].map(String).sort());
|
|
5846
|
-
const rules = {};
|
|
5847
|
-
for (const [rule, value] of Object.entries(isRecord(block.rules) ? block.rules : {})) {
|
|
5848
|
-
const presetSpelling = governed.get(canonicalRuleName(rule));
|
|
5849
|
-
if (presetSpelling === void 0) rules[rule] = value;
|
|
5850
|
-
else
|
|
5851
|
-
dropped.push(
|
|
5852
|
-
`overrides[${block.files.join(", ")}] ${describeRuleKey(rule, presetSpelling)}`
|
|
5853
|
-
);
|
|
5854
|
-
}
|
|
5855
|
-
const { rules: _rules, ...rest } = block;
|
|
5856
|
-
const merged = byFiles.get(files);
|
|
5857
|
-
if (merged === void 0) {
|
|
5858
|
-
byFiles.set(files, { ...rest, ...Object.keys(rules).length > 0 ? { rules } : {} });
|
|
5859
|
-
continue;
|
|
5860
|
-
}
|
|
5861
|
-
const { files: _sameFiles, ...others } = rest;
|
|
5862
|
-
const mergedRules = { ...isRecord(merged.rules) ? merged.rules : {}, ...rules };
|
|
5863
|
-
Object.assign(
|
|
5864
|
-
merged,
|
|
5865
|
-
others,
|
|
5866
|
-
Object.keys(mergedRules).length > 0 ? { rules: mergedRules } : {}
|
|
5867
|
-
);
|
|
5868
|
-
}
|
|
5869
|
-
const own = [...byFiles.values()].filter((block) => Object.keys(block).length > 1);
|
|
5870
|
-
if (own.length > 0) {
|
|
5871
|
-
blocks.overrides = own;
|
|
5872
|
-
kept.push(
|
|
5873
|
-
`kept ${own.length} override block(s) this module set (${own.map((block) => block.files.join(", ")).join("; ")})`
|
|
5874
|
-
);
|
|
5875
|
-
}
|
|
5876
|
-
}
|
|
5877
|
-
return { blocks, kept, dropped };
|
|
5878
|
-
}
|
|
5879
|
-
|
|
5880
3394
|
// src/roles/lint/parse-diagnostics.ts
|
|
5881
3395
|
function ruleId(code) {
|
|
5882
3396
|
const inner = /\(([^)]+)\)/.exec(code);
|
|
@@ -5926,26 +3440,6 @@ function errorCountsByConfigRule(stdout) {
|
|
|
5926
3440
|
return counts;
|
|
5927
3441
|
}
|
|
5928
3442
|
|
|
5929
|
-
// src/roles/lint/presets.ts
|
|
5930
|
-
var hasRuleData = (name) => GENERATED_LINT_PRESETS.includes(name);
|
|
5931
|
-
function lintPresetFor(preset) {
|
|
5932
|
-
const file = presetFile(preset);
|
|
5933
|
-
const resolved = hasRuleData(preset) ? preset : "node";
|
|
5934
|
-
return {
|
|
5935
|
-
plugins: file.plugins,
|
|
5936
|
-
jsPlugins: file.jsPlugins,
|
|
5937
|
-
...file.settings === null ? {} : { settings: file.settings },
|
|
5938
|
-
...file.renames ? { renames: file.renames } : {},
|
|
5939
|
-
...file.overrides ? {
|
|
5940
|
-
overrides: file.overrides.map((override, index) => ({
|
|
5941
|
-
files: override.files,
|
|
5942
|
-
rules: toRuleMap(`${preset} override ${index}`, override.rules)
|
|
5943
|
-
}))
|
|
5944
|
-
} : {},
|
|
5945
|
-
rules: rulesFor(resolved)
|
|
5946
|
-
};
|
|
5947
|
-
}
|
|
5948
|
-
|
|
5949
3443
|
// src/roles/lint/adapters/oxlint/plan.ts
|
|
5950
3444
|
import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
|
|
5951
3445
|
import { join as join20 } from "node:path";
|
|
@@ -6229,7 +3723,7 @@ function plan2(context2) {
|
|
|
6229
3723
|
const carried = [.../* @__PURE__ */ new Set([...DEFAULT_IGNORE_PATTERNS, ...moduleOwn])];
|
|
6230
3724
|
const committed = committedConfig(context2.cwd);
|
|
6231
3725
|
const { kept: teamRules, governed: droppedRules } = moduleOwnRules(
|
|
6232
|
-
|
|
3726
|
+
isRecord(committed.rules) ? committed.rules : {},
|
|
6233
3727
|
lintPresetFor(variant)
|
|
6234
3728
|
);
|
|
6235
3729
|
const teamBlocks = moduleOwnBlocks(committed, lintPresetFor(variant));
|
|
@@ -6375,14 +3869,14 @@ function committedExtends(cwd) {
|
|
|
6375
3869
|
return [];
|
|
6376
3870
|
}
|
|
6377
3871
|
}
|
|
6378
|
-
var
|
|
3872
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6379
3873
|
function committedConfig(cwd) {
|
|
6380
3874
|
try {
|
|
6381
3875
|
const parsed = parseJsonc(
|
|
6382
3876
|
readFileSync14(join20(cwd, LINT_CONFIG_FILE), "utf8"),
|
|
6383
3877
|
LINT_CONFIG_FILE
|
|
6384
3878
|
);
|
|
6385
|
-
return
|
|
3879
|
+
return isRecord(parsed) ? parsed : {};
|
|
6386
3880
|
} catch {
|
|
6387
3881
|
return {};
|
|
6388
3882
|
}
|
|
@@ -6777,7 +4271,11 @@ ${result.stderr ?? ""}`);
|
|
|
6777
4271
|
// else here: the stub still holds only `extends` and `ignorePatterns`, so a module with
|
|
6778
4272
|
// a team layer reports `conformant=true drift=[]` and used to say nothing at all about
|
|
6779
4273
|
// the extra rules it runs. See `extra-layers` for why that state is legitimate.
|
|
6780
|
-
layers: extraLayers(ctx.cwd, committedExtendsList(ctx.cwd, LINT_CONFIG_FILE))
|
|
4274
|
+
layers: extraLayers(ctx.cwd, committedExtendsList(ctx.cwd, LINT_CONFIG_FILE)),
|
|
4275
|
+
// What this module ADDS in its own stub: rules the preset does not name. Not drift, by the
|
|
4276
|
+
// criterion a re-init keeps them by, so without this list they would be invisible. A rule
|
|
4277
|
+
// the preset names, set differently, is not here: it is a conflict, reported as drift.
|
|
4278
|
+
...describeAdditions(readModuleAdditions(ctx.cwd))
|
|
6781
4279
|
};
|
|
6782
4280
|
}
|
|
6783
4281
|
/** How many rules the extended preset enforces, read from the preset on disk. */
|
|
@@ -6919,6 +4417,28 @@ ${result.stderr ?? ""}`);
|
|
|
6919
4417
|
);
|
|
6920
4418
|
}
|
|
6921
4419
|
};
|
|
4420
|
+
function describeAdditions(additions) {
|
|
4421
|
+
return {
|
|
4422
|
+
added: additions.rules.map((entry) => ({
|
|
4423
|
+
rule: entry.rule,
|
|
4424
|
+
...entry.files === void 0 ? {} : { files: entry.files },
|
|
4425
|
+
value: entry.value,
|
|
4426
|
+
reason: describeAddition(entry.value, entry.files)
|
|
4427
|
+
})),
|
|
4428
|
+
addedConfig: additions.config.map((entry) => ({
|
|
4429
|
+
entry: entry.entry,
|
|
4430
|
+
key: entry.key,
|
|
4431
|
+
...entry.files === void 0 ? {} : { files: entry.files },
|
|
4432
|
+
value: entry.value,
|
|
4433
|
+
reason: typeof entry.value === "string" ? "the preset does not set it" : `${JSON.stringify(entry.value)}: the preset does not set it`
|
|
4434
|
+
}))
|
|
4435
|
+
};
|
|
4436
|
+
}
|
|
4437
|
+
function describeAddition(value, files) {
|
|
4438
|
+
const where = files === void 0 ? "" : ` for ${files.join(", ")}`;
|
|
4439
|
+
const off = files === void 0 && isOffRuleValue(value) ? "; off changes nothing, since a rule the preset does not name is already off" : "";
|
|
4440
|
+
return `${JSON.stringify(value)}${where}: the preset does not name this rule${off}`;
|
|
4441
|
+
}
|
|
6922
4442
|
|
|
6923
4443
|
// src/roles/lint/register.ts
|
|
6924
4444
|
function registerLint() {
|
|
@@ -10749,7 +8269,7 @@ import { createRequire } from "node:module";
|
|
|
10749
8269
|
import { join as join33 } from "node:path";
|
|
10750
8270
|
|
|
10751
8271
|
// src/roles/typescript/presets/nest.json
|
|
10752
|
-
var
|
|
8272
|
+
var nest_default = {
|
|
10753
8273
|
compilerOptions: {
|
|
10754
8274
|
module: "esnext",
|
|
10755
8275
|
moduleResolution: "bundler",
|
|
@@ -10766,7 +8286,7 @@ var nest_default2 = {
|
|
|
10766
8286
|
};
|
|
10767
8287
|
|
|
10768
8288
|
// src/roles/typescript/presets/node.json
|
|
10769
|
-
var
|
|
8289
|
+
var node_default = {
|
|
10770
8290
|
compilerOptions: {
|
|
10771
8291
|
module: "esnext",
|
|
10772
8292
|
moduleResolution: "bundler",
|
|
@@ -10779,7 +8299,7 @@ var node_default2 = {
|
|
|
10779
8299
|
};
|
|
10780
8300
|
|
|
10781
8301
|
// src/roles/typescript/presets/react.json
|
|
10782
|
-
var
|
|
8302
|
+
var react_default = {
|
|
10783
8303
|
compilerOptions: {
|
|
10784
8304
|
target: "ES2023",
|
|
10785
8305
|
lib: ["ES2023", "DOM", "DOM.Iterable"],
|
|
@@ -10798,7 +8318,7 @@ var react_default2 = {
|
|
|
10798
8318
|
};
|
|
10799
8319
|
|
|
10800
8320
|
// src/roles/typescript/presets/shared.json
|
|
10801
|
-
var
|
|
8321
|
+
var shared_default2 = {
|
|
10802
8322
|
$schema: "https://json.schemastore.org/tsconfig",
|
|
10803
8323
|
compilerOptions: {
|
|
10804
8324
|
strict: true,
|
|
@@ -10824,15 +8344,15 @@ var shared_default3 = {
|
|
|
10824
8344
|
};
|
|
10825
8345
|
|
|
10826
8346
|
// src/roles/typescript/preset-data.ts
|
|
10827
|
-
var SHARED =
|
|
8347
|
+
var SHARED = shared_default2;
|
|
10828
8348
|
var LAYERS = {
|
|
10829
|
-
nest:
|
|
10830
|
-
node:
|
|
10831
|
-
react:
|
|
8349
|
+
nest: nest_default,
|
|
8350
|
+
node: node_default,
|
|
8351
|
+
react: react_default
|
|
10832
8352
|
};
|
|
10833
8353
|
var SHIPPED_PRESETS = Object.keys(LAYERS).sort();
|
|
10834
8354
|
var DEFERRED_RULES = Object.entries(SHARED.deferred ?? {}).map(([rule, entry]) => ({ rule, phase: entry.phase, reason: entry.reason })).sort((left, right) => left.rule.localeCompare(right.rule));
|
|
10835
|
-
function
|
|
8355
|
+
function validate() {
|
|
10836
8356
|
for (const { rule, phase, reason } of DEFERRED_RULES) {
|
|
10837
8357
|
if (!Number.isInteger(phase) || phase < 2) {
|
|
10838
8358
|
throw new Error(
|
|
@@ -10858,7 +8378,7 @@ function validate2() {
|
|
|
10858
8378
|
}
|
|
10859
8379
|
}
|
|
10860
8380
|
}
|
|
10861
|
-
|
|
8381
|
+
validate();
|
|
10862
8382
|
function hasShippedPreset(preset) {
|
|
10863
8383
|
return preset in LAYERS;
|
|
10864
8384
|
}
|