@isentinel/eslint-config 6.0.0-beta.45 → 6.0.0-beta.46
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 +37 -7
- package/dist/cli.mjs +3 -3
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +4 -4
- package/dist/lint-cli.mjs +444 -208
- package/dist/lint-ignored.mjs +8 -6
- package/dist/oxlint.d.mts +5 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -255,8 +255,8 @@ Other behaviours:
|
|
|
255
255
|
(see `FAST_FILES_PER_WORKER`) than the type-aware pass.
|
|
256
256
|
- Keeps a separate ESLint cache per pass so they never invalidate one another:
|
|
257
257
|
`.eslintcache-fast-<key>` (fast pass), `.eslintcache-typeaware-<key>`
|
|
258
|
-
(type-aware pass), and `.eslintcache-<key>` (the full
|
|
259
|
-
|
|
258
|
+
(type-aware pass), and `.eslintcache-<key>` (the full config, used by CI,
|
|
259
|
+
`--type-aware=full` and the fix child below). A change to an
|
|
260
260
|
ESLint/oxlint/Prettier/tsconfig file or a lockfile clears each cache that is
|
|
261
261
|
actually older than that change; a change to the root `package.json`
|
|
262
262
|
resolution surface (`exports`, `imports`, `main`, `module`, `types`,
|
|
@@ -281,16 +281,46 @@ Other behaviours:
|
|
|
281
281
|
value naming that branch. It is folded into the key, giving those configs
|
|
282
282
|
separate caches too.
|
|
283
283
|
|
|
284
|
-
-
|
|
285
|
-
|
|
284
|
+
- Treats `--fix` as a check followed by a fix, in three steps. `oxlint --fix`
|
|
285
|
+
goes first and alone, since it rewrites the files the ESLint children are
|
|
286
|
+
about to read. The run's ESLint passes then run as ordinary **checks** —
|
|
287
|
+
concurrent, own caches, no writes. By default those are the fast and
|
|
288
|
+
type-aware passes — the single full pass in CI; an explicit `--type-aware`
|
|
289
|
+
checks whichever passes that mode selects instead (`full` the single full
|
|
290
|
+
pass, `only` the type-aware pass alone, `off` the fast pass alone). Finally
|
|
291
|
+
**one** ESLint child applies fixes to **only the files those checks had
|
|
292
|
+
messages about**, using the full config (a superset of every pass, so it can
|
|
293
|
+
fix anything any of them found).
|
|
294
|
+
|
|
295
|
+
When the checks report nothing, which is the common case, that last child
|
|
296
|
+
never spawns and `--fix` costs what a check run costs. Being the run's only
|
|
297
|
+
ESLint writer, it also cannot race anything.
|
|
298
|
+
|
|
299
|
+
The file list comes from the check passes' own caches: ESLint stores each
|
|
300
|
+
file's result beside its cache entry and replays it on a cache hit, so a warm
|
|
301
|
+
cache is that pass's whole-tree verdict — including for a pass that
|
|
302
|
+
auto-skipped, whose verdict stands precisely because nothing it cares about
|
|
303
|
+
changed. `--no-cache` leaves no verdict to read, so the fix child falls back
|
|
304
|
+
to linting everything it was given. A target outside the working directory is
|
|
305
|
+
invisible to the listing the verdict is read against, so it is handed to the
|
|
306
|
+
fix child as it stands, alongside the reported files; that child runs without
|
|
307
|
+
the cache, since a stale entry for a file no verdict covers would let ESLint
|
|
308
|
+
skip it.
|
|
309
|
+
|
|
286
310
|
- Lets every child run to completion and returns non-zero if any failed — an
|
|
287
311
|
ordinary lint error in one tool no longer kills the others mid-run.
|
|
288
312
|
|
|
289
313
|
> **Unused eslint-disable directives.** The default two-pass mode does **not**
|
|
290
314
|
> report unused `eslint-disable` directives: a directive naming a rule that
|
|
291
315
|
> lives in the _other_ pass would look unused to the pass that runs it and
|
|
292
|
-
> produce a false positive.
|
|
293
|
-
>
|
|
316
|
+
> produce a false positive. CI and `--type-aware=full` runs use the single full
|
|
317
|
+
> config and still report them.
|
|
318
|
+
>
|
|
319
|
+
> A local `--fix` inherits this from its checks. The fix child runs the full
|
|
320
|
+
> config and would report an unused directive, but it only ever sees the files
|
|
321
|
+
> the checks reported, and a file whose _only_ problem is an unused directive is
|
|
322
|
+
> not one of them — so those directives survive a local fix run. In CI the check
|
|
323
|
+
> is the full config, so they are reported and removed as before.
|
|
294
324
|
|
|
295
325
|
### Hybrid detection
|
|
296
326
|
|
|
@@ -317,7 +347,7 @@ Any trailing positional arguments are treated as paths to lint (default `.`).
|
|
|
317
347
|
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
318
348
|
| `--eslint` | Run only ESLint. |
|
|
319
349
|
| `--oxlint` | Run only oxlint. |
|
|
320
|
-
| `--fix` |
|
|
350
|
+
| `--fix` | Check as usual, then fix only the files the checks reported (one child). |
|
|
321
351
|
| `--agents`, `--no-agents` | Force agent-friendly output from both linters on or off (default: on in an agent session). |
|
|
322
352
|
| `--type-aware=off\|only\|full` | Force a single ESLint pass: `off` fast-only, `only` type-aware-only, `full` the whole config in one pass. Cannot mix with `--fix`. |
|
|
323
353
|
| `--no-oxlint-type-aware` | Skip oxlint's type-aware rules (no `oxlint-tsgolint` needed). |
|
package/dist/cli.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import path from "node:path";
|
|
|
9
9
|
import { existsSync, readFileSync } from "fs";
|
|
10
10
|
import { execSync } from "node:child_process";
|
|
11
11
|
//#region package.json
|
|
12
|
-
var version = "6.0.0-beta.
|
|
12
|
+
var version = "6.0.0-beta.46";
|
|
13
13
|
var package_default = {
|
|
14
14
|
name: "@isentinel/eslint-config",
|
|
15
15
|
version,
|
|
@@ -175,7 +175,7 @@ var package_default = {
|
|
|
175
175
|
},
|
|
176
176
|
peerDependencies: {
|
|
177
177
|
"@vitest/eslint-plugin": "^1.6.4",
|
|
178
|
-
"eslint": "^10.
|
|
178
|
+
"eslint": "^10.10.0",
|
|
179
179
|
"eslint-plugin-eslint-plugin": "^7.5.0",
|
|
180
180
|
"eslint-plugin-jest": "^29.15.0",
|
|
181
181
|
"eslint-plugin-jest-extended": "^3.0.0",
|
|
@@ -534,7 +534,7 @@ async function updateEslintFiles(result) {
|
|
|
534
534
|
//#endregion
|
|
535
535
|
//#region src/cli/constants-generated.ts
|
|
536
536
|
const versionsMap = {
|
|
537
|
-
"eslint": "10.
|
|
537
|
+
"eslint": "10.10.0",
|
|
538
538
|
"eslint-plugin-jest": "29.16.0",
|
|
539
539
|
"eslint-plugin-react-jsx": "5.17.3",
|
|
540
540
|
"eslint-plugin-react-naming-convention": "5.17.3",
|
package/dist/index.d.mts
CHANGED
|
@@ -1510,7 +1510,9 @@ interface MainRuleDefaults {
|
|
|
1510
1510
|
"*": "off";
|
|
1511
1511
|
};
|
|
1512
1512
|
"no-unmodified-loop-condition": {
|
|
1513
|
-
"*": "error"
|
|
1513
|
+
"*": ["error", {
|
|
1514
|
+
"checkConditionalExpressions": false;
|
|
1515
|
+
}];
|
|
1514
1516
|
};
|
|
1515
1517
|
"no-unneeded-ternary": {
|
|
1516
1518
|
"*": ["error", {
|
|
@@ -6498,7 +6500,7 @@ interface OverrideSiteChains {
|
|
|
6498
6500
|
type TestChain = [TestRuleDefaults, SourceFeatureRuleDefaults, MainRuleDefaults];
|
|
6499
6501
|
type ValidateOptionsWith<O, VK extends VariantKey> = ValidateSite<O, "rules", MainChain, VK> & ValidateSubOptionsFromTable<O, OverrideSiteChains, VK> & ValidateTestOption<O, TestChain, VK>;
|
|
6500
6502
|
//#endregion
|
|
6501
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/
|
|
6503
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/48bee61dfbd6416cb227d1c477eb8990bf234fa634e4ccd62a9520a90cc26602/node_modules/eslint-config-flat-gitignore/dist/index.d.mts
|
|
6502
6504
|
interface FlatGitignoreOptions {
|
|
6503
6505
|
/**
|
|
6504
6506
|
* Name of the configuration.
|
|
@@ -9343,7 +9345,7 @@ interface RuleOptions {
|
|
|
9343
9345
|
* Disallow unmodified loop conditions
|
|
9344
9346
|
* @see https://eslint.org/docs/latest/rules/no-unmodified-loop-condition
|
|
9345
9347
|
*/
|
|
9346
|
-
'no-unmodified-loop-condition'?: Linter.RuleEntry<
|
|
9348
|
+
'no-unmodified-loop-condition'?: Linter.RuleEntry<NoUnmodifiedLoopCondition>;
|
|
9347
9349
|
/**
|
|
9348
9350
|
* Disallow ternary operators when simpler alternatives exist
|
|
9349
9351
|
* @see https://eslint.org/docs/latest/rules/no-unneeded-ternary
|
|
@@ -19662,6 +19664,10 @@ type NoUnderscoreDangle = [] | [{
|
|
|
19662
19664
|
allowInArrayDestructuring?: boolean;
|
|
19663
19665
|
allowInObjectDestructuring?: boolean;
|
|
19664
19666
|
}];
|
|
19667
|
+
// ----- no-unmodified-loop-condition -----
|
|
19668
|
+
type NoUnmodifiedLoopCondition = [] | [{
|
|
19669
|
+
checkConditionalExpressions?: boolean;
|
|
19670
|
+
}];
|
|
19665
19671
|
// ----- no-unneeded-ternary -----
|
|
19666
19672
|
type NoUnneededTernary = [] | [{
|
|
19667
19673
|
defaultAssignment?: boolean;
|
package/dist/index.mjs
CHANGED
|
@@ -1889,7 +1889,7 @@ async function flawless(options = {}, prettierOptions = {}) {
|
|
|
1889
1889
|
];
|
|
1890
1890
|
}
|
|
1891
1891
|
//#endregion
|
|
1892
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@eslint/compat/2.1.0/
|
|
1892
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@eslint/compat/2.1.0/c5793be99df3f1294a68a791ed84f1ed609714ef294e5fa5fdeeff97455db3c8/node_modules/@eslint/compat/dist/esm/index.js
|
|
1893
1893
|
/**
|
|
1894
1894
|
* @fileoverview Ignore file utilities for the compat package.
|
|
1895
1895
|
* @author Nicholas C. Zakas
|
|
@@ -1918,7 +1918,7 @@ function convertIgnorePatternToMinimatch(pattern) {
|
|
|
1918
1918
|
}
|
|
1919
1919
|
var init_esm$1 = __esmMin((() => {}));
|
|
1920
1920
|
//#endregion
|
|
1921
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/
|
|
1921
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-config-flat-gitignore/2.3.0/48bee61dfbd6416cb227d1c477eb8990bf234fa634e4ccd62a9520a90cc26602/node_modules/eslint-config-flat-gitignore/dist/index.mjs
|
|
1922
1922
|
var dist_exports = /* @__PURE__ */ __exportAll$2({ default: () => ignore });
|
|
1923
1923
|
function toArray(array) {
|
|
1924
1924
|
array = array ?? [];
|
|
@@ -6250,7 +6250,7 @@ async function unicorn({ complementIgnores, nameReplacements, roblox = true, roo
|
|
|
6250
6250
|
];
|
|
6251
6251
|
}
|
|
6252
6252
|
//#endregion
|
|
6253
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/
|
|
6253
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/eedfb7e8cfd566a06319a5894d49f61723d6a8793c9b4a69e6556dd999563774/node_modules/eslint-plugin-yml/lib/chunk-CfYAbeIz.mjs
|
|
6254
6254
|
var __defProp$1, __exportAll$1;
|
|
6255
6255
|
var init_chunk_CfYAbeIz = __esmMin((() => {
|
|
6256
6256
|
__defProp$1 = Object.defineProperty;
|
|
@@ -9433,7 +9433,7 @@ var init_lib$1 = __esmMin((() => {
|
|
|
9433
9433
|
({ ...meta_exports$1 });
|
|
9434
9434
|
}));
|
|
9435
9435
|
//#endregion
|
|
9436
|
-
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/
|
|
9436
|
+
//#region ../../../setup-pnpm/node_modules/.bin/store/v11/links/@/eslint-plugin-yml/3.5.0/eedfb7e8cfd566a06319a5894d49f61723d6a8793c9b4a69e6556dd999563774/node_modules/eslint-plugin-yml/lib/index.mjs
|
|
9437
9437
|
var lib_exports = /* @__PURE__ */ __exportAll$2({
|
|
9438
9438
|
configs: () => configs,
|
|
9439
9439
|
default: () => src_default,
|
package/dist/lint-cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import process$1 from "node:process";
|
|
3
|
-
import {
|
|
3
|
+
import { isPackageExists } from "local-pkg";
|
|
4
4
|
import yargs from "yargs";
|
|
5
5
|
import "find-up-simple";
|
|
6
6
|
import fs from "node:fs";
|
|
@@ -38,7 +38,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
38
38
|
}) : target, mod));
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region package.json
|
|
41
|
-
var version = "6.0.0-beta.
|
|
41
|
+
var version = "6.0.0-beta.46";
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/lint-cli/lib/cli/types.ts
|
|
44
44
|
/**
|
|
@@ -315,7 +315,7 @@ function parseArguments(argv, environment = process$1.env) {
|
|
|
315
315
|
description: "Run only oxlint.",
|
|
316
316
|
type: "boolean"
|
|
317
317
|
}).option("fix", {
|
|
318
|
-
description: "
|
|
318
|
+
description: "Fix the files the checks reported.",
|
|
319
319
|
type: "boolean"
|
|
320
320
|
}).option("agents", {
|
|
321
321
|
description: "Agent-friendly output (default: on in an agent session).",
|
|
@@ -349,7 +349,7 @@ function parseArguments(argv, environment = process$1.env) {
|
|
|
349
349
|
const oxlintOnly = parsed.oxlint === true;
|
|
350
350
|
const { typeAware } = parsed;
|
|
351
351
|
const fix = parsed.fix === true;
|
|
352
|
-
if (fix && typeAware !== void 0) throw new CliError("Cannot combine --fix with --type-aware;
|
|
352
|
+
if (fix && typeAware !== void 0) throw new CliError("Cannot combine --fix with --type-aware; the fix child always uses the full config.");
|
|
353
353
|
const eslintArgs = eslintExtract.value !== void 0 ? splitArgs(eslintExtract.value) : [];
|
|
354
354
|
const oxlintArgs = oxlintExtract.value !== void 0 ? splitArgs(oxlintExtract.value) : [];
|
|
355
355
|
const rawPassthrough = parsed["--"];
|
|
@@ -474,7 +474,157 @@ function resolveRunContext(cwd, environment, mutate) {
|
|
|
474
474
|
};
|
|
475
475
|
}
|
|
476
476
|
//#endregion
|
|
477
|
+
//#region src/lint-cli/lib/state.ts
|
|
478
|
+
/**
|
|
479
|
+
* Directory (relative to the project root) where the CLI keeps its persisted
|
|
480
|
+
* state. Lives under `node_modules/.cache` so it is discarded with the
|
|
481
|
+
* dependency tree and never committed.
|
|
482
|
+
*/
|
|
483
|
+
const CACHE_DIRECTORY = path.join("node_modules", ".cache", "isentinel-lint");
|
|
484
|
+
/**
|
|
485
|
+
* The directory every state file lives in.
|
|
486
|
+
*
|
|
487
|
+
* @param cwd - The consumer project root.
|
|
488
|
+
* @returns The absolute path to the runner's cache directory.
|
|
489
|
+
*/
|
|
490
|
+
function stateDirectory(cwd) {
|
|
491
|
+
return path.resolve(cwd, CACHE_DIRECTORY);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Resolve one state file inside {@link stateDirectory}.
|
|
495
|
+
*
|
|
496
|
+
* @param cwd - The consumer project root.
|
|
497
|
+
* @param name - The state's base name.
|
|
498
|
+
* @param parts - Further hyphen-joined segments, usually the config-variant key
|
|
499
|
+
* from `resolveCacheKey`. State that is consumed once (a stored hash, a
|
|
500
|
+
* drained builder) must carry that key, or the first variant to run absorbs
|
|
501
|
+
* the change on behalf of all of them.
|
|
502
|
+
* @returns The absolute path to the state file.
|
|
503
|
+
*/
|
|
504
|
+
function statePath(cwd, name, ...parts) {
|
|
505
|
+
return path.join(stateDirectory(cwd), [name, ...parts].join("-"));
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Read a UTF-8 file, or `undefined` when it cannot be read for any reason.
|
|
509
|
+
* Shared by every tolerant read in the CLI: state files, and the config-import
|
|
510
|
+
* closure walk.
|
|
511
|
+
*
|
|
512
|
+
* @param filePath - The file to read.
|
|
513
|
+
* @returns The file's content, or `undefined`.
|
|
514
|
+
*/
|
|
515
|
+
function readFileIfPresent(filePath) {
|
|
516
|
+
try {
|
|
517
|
+
return fs.readFileSync(filePath, "utf8");
|
|
518
|
+
} catch {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Read a state file written by {@link writeState}. Every failure mode — the
|
|
524
|
+
* file is missing, unreadable, malformed, or was written by another
|
|
525
|
+
* {@link STATE_VERSION} — degrades to `undefined`, which every caller treats as
|
|
526
|
+
* "unknown" and recomputes from.
|
|
527
|
+
*
|
|
528
|
+
* @template T - The shape this file's writer stores. Asserted, not checked:
|
|
529
|
+
* only the schema version is verified, exactly as the per-module casts this
|
|
530
|
+
* replaced did.
|
|
531
|
+
* @param filePath - The state file, from {@link statePath}.
|
|
532
|
+
* @returns The stored payload, or `undefined`.
|
|
533
|
+
*/
|
|
534
|
+
function readState(filePath) {
|
|
535
|
+
const raw = readFileIfPresent(filePath);
|
|
536
|
+
return raw === void 0 ? void 0 : parseState(raw);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Persist a state payload, creating the cache directory as needed.
|
|
540
|
+
*
|
|
541
|
+
* The write is atomic (temp file plus rename), since `plan()` runs concurrently
|
|
542
|
+
* across packages in a parallel per-package lint setup and a torn file would be
|
|
543
|
+
* read back as "unknown" at best.
|
|
544
|
+
*
|
|
545
|
+
* Best-effort — a failed write leaves the state unknown, so the next run
|
|
546
|
+
* recomputes rather than trusting something stale.
|
|
547
|
+
*
|
|
548
|
+
* @param filePath - The state file, from {@link statePath}.
|
|
549
|
+
* @param data - The payload to store.
|
|
550
|
+
*/
|
|
551
|
+
function writeState(filePath, data) {
|
|
552
|
+
const content = `${JSON.stringify({
|
|
553
|
+
data,
|
|
554
|
+
version: 2
|
|
555
|
+
})}\n`;
|
|
556
|
+
const temporary = `${filePath}.${process$1.pid}.tmp`;
|
|
557
|
+
try {
|
|
558
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
559
|
+
fs.writeFileSync(temporary, content);
|
|
560
|
+
fs.renameSync(temporary, filePath);
|
|
561
|
+
} catch {
|
|
562
|
+
try {
|
|
563
|
+
fs.rmSync(temporary, { force: true });
|
|
564
|
+
} catch {}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Compare a value against the stored one and replace it when they differ, the
|
|
569
|
+
* compare-and-swap every hash-drift bust runs: the caller acts on the outcome
|
|
570
|
+
* and never on the stored value itself.
|
|
571
|
+
*
|
|
572
|
+
* The value is consumed by the swap — once stored, every later run reads back
|
|
573
|
+
* `"unchanged"` — which is why hash state is keyed per config variant.
|
|
574
|
+
*
|
|
575
|
+
* A stored value this {@link STATE_VERSION} cannot read counts as `"changed"`,
|
|
576
|
+
* so a CLI upgrade invalidates rather than silently adopts what it finds.
|
|
577
|
+
*
|
|
578
|
+
* @param filePath - The state file, from {@link statePath}.
|
|
579
|
+
* @param value - The value this run computed.
|
|
580
|
+
* @returns How the stored value compared.
|
|
581
|
+
*/
|
|
582
|
+
function swapState(filePath, value) {
|
|
583
|
+
const raw = readFileIfPresent(filePath);
|
|
584
|
+
if ((raw === void 0 ? void 0 : parseState(raw)) === value) return "unchanged";
|
|
585
|
+
writeState(filePath, value);
|
|
586
|
+
return raw === void 0 ? "first" : "changed";
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Refresh a state file's mtime without rewriting it, so a reader comparing that
|
|
590
|
+
* mtime against another file's still sees the state as fresh. Best-effort: a
|
|
591
|
+
* missing file simply stays missing.
|
|
592
|
+
*
|
|
593
|
+
* @param filePath - The state file, from {@link statePath}.
|
|
594
|
+
*/
|
|
595
|
+
function touchState(filePath) {
|
|
596
|
+
try {
|
|
597
|
+
const now = Date.now() / 1e3;
|
|
598
|
+
fs.utimesSync(filePath, now, now);
|
|
599
|
+
} catch {}
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Parse one state file's content, or `undefined` when it is malformed or
|
|
603
|
+
* carries another {@link STATE_VERSION}.
|
|
604
|
+
*
|
|
605
|
+
* @template T - The shape this file's writer stores (asserted, not checked).
|
|
606
|
+
* @param raw - The file's content.
|
|
607
|
+
* @returns The stored payload, or `undefined`.
|
|
608
|
+
*/
|
|
609
|
+
function parseState(raw) {
|
|
610
|
+
let parsed;
|
|
611
|
+
try {
|
|
612
|
+
parsed = JSON.parse(raw);
|
|
613
|
+
} catch {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (typeof parsed !== "object" || parsed === null) return;
|
|
617
|
+
const envelope = parsed;
|
|
618
|
+
return envelope.version === 2 ? envelope.data : void 0;
|
|
619
|
+
}
|
|
620
|
+
//#endregion
|
|
477
621
|
//#region src/lint-cli/lib/exec/resolve.ts
|
|
622
|
+
/**
|
|
623
|
+
* A synthetic basename for `createRequire`, which resolves relative to a file
|
|
624
|
+
* rather than a directory. Spelled so it can never collide with a real consumer
|
|
625
|
+
* module.
|
|
626
|
+
*/
|
|
627
|
+
const RESOLVE_ANCHOR = "__isentinel-lint__.js";
|
|
478
628
|
/** Memoised {@link resolveLocalBin} results, keyed by `cwd\0name`. */
|
|
479
629
|
const localBinCache = /* @__PURE__ */ new Map();
|
|
480
630
|
/**
|
|
@@ -484,6 +634,10 @@ const localBinCache = /* @__PURE__ */ new Map();
|
|
|
484
634
|
* Windows `.cmd`/`.ps1` quoting hazards. Memoised so the two ESLint passes
|
|
485
635
|
* resolve the same bin once.
|
|
486
636
|
*
|
|
637
|
+
* The walk is Node's own rather than a hand-rolled one: inside a worktree
|
|
638
|
+
* nested in its own checkout the two disagree, and taking the ancestor's copy
|
|
639
|
+
* silently runs a different version of the linter than every other tool sees.
|
|
640
|
+
*
|
|
487
641
|
* @param name - The package name to resolve (for example `eslint`).
|
|
488
642
|
* @param cwd - The directory to resolve from.
|
|
489
643
|
* @returns The absolute path to the package's JavaScript entry.
|
|
@@ -492,12 +646,11 @@ function resolveLocalBin(name, cwd) {
|
|
|
492
646
|
const cacheKey = `${cwd}\0${name}`;
|
|
493
647
|
const cached = localBinCache.get(cacheKey);
|
|
494
648
|
if (cached !== void 0) return cached;
|
|
495
|
-
const
|
|
496
|
-
if (
|
|
497
|
-
const
|
|
498
|
-
const relative = typeof bin === "string" ? bin : bin?.[name];
|
|
649
|
+
const manifestPath = resolveManifest(name, cwd);
|
|
650
|
+
if (manifestPath === void 0) throw new CliError(`Could not find "${name}". Install it in this project to run isentinel-lint.`);
|
|
651
|
+
const relative = readBinEntry(manifestPath, name);
|
|
499
652
|
if (relative === void 0) throw new CliError(`Package "${name}" does not declare a "${name}" bin entry.`);
|
|
500
|
-
const resolved = path.resolve(
|
|
653
|
+
const resolved = path.resolve(path.dirname(manifestPath), relative);
|
|
501
654
|
localBinCache.set(cacheKey, resolved);
|
|
502
655
|
return resolved;
|
|
503
656
|
}
|
|
@@ -537,6 +690,50 @@ function resolveIgnoredHelper() {
|
|
|
537
690
|
const built = fileURLToPath(new URL("./lint-ignored.mjs", import.meta.url));
|
|
538
691
|
return fs.existsSync(built) ? built : fileURLToPath(new URL("../../ignored-child.ts", import.meta.url));
|
|
539
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* The path a package's manifest declares as the bin of the package's own name,
|
|
695
|
+
* relative to the package root. Both the shorthand string form and the map form
|
|
696
|
+
* count.
|
|
697
|
+
*
|
|
698
|
+
* @param manifestPath - The absolute path to the package's `package.json`.
|
|
699
|
+
* @param name - The bin name to look for.
|
|
700
|
+
* @returns The declared relative path, or undefined when there is none.
|
|
701
|
+
*/
|
|
702
|
+
function readBinEntry(manifestPath, name) {
|
|
703
|
+
const raw = readFileIfPresent(manifestPath);
|
|
704
|
+
if (raw === void 0) return;
|
|
705
|
+
let parsed;
|
|
706
|
+
try {
|
|
707
|
+
parsed = JSON.parse(raw);
|
|
708
|
+
} catch {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (!isRecord(parsed)) return;
|
|
712
|
+
const { bin } = parsed;
|
|
713
|
+
if (typeof bin === "string") return bin;
|
|
714
|
+
const entry = isRecord(bin) ? bin[name] : void 0;
|
|
715
|
+
return typeof entry === "string" ? entry : void 0;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Locate a package's manifest exactly as a `require` call from `cwd` would.
|
|
719
|
+
*
|
|
720
|
+
* Reads the manifest as a subpath, so a package whose `exports` map hides
|
|
721
|
+
* `./package.json` counts as unresolvable. Both packages this serves publish
|
|
722
|
+
* it, and one that does not could not be spawned from its `bin` field anyway.
|
|
723
|
+
*
|
|
724
|
+
* @param name - The package name to resolve.
|
|
725
|
+
* @param cwd - The directory to resolve from.
|
|
726
|
+
* @returns The absolute path to the package's `package.json`, or undefined when
|
|
727
|
+
* the package is not installed.
|
|
728
|
+
*/
|
|
729
|
+
function resolveManifest(name, cwd) {
|
|
730
|
+
const require = createRequire(path.join(cwd, RESOLVE_ANCHOR));
|
|
731
|
+
try {
|
|
732
|
+
return require.resolve(`${name}/package.json`);
|
|
733
|
+
} catch {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
540
737
|
//#endregion
|
|
541
738
|
//#region src/lint-cli/lib/exec/shell.ts
|
|
542
739
|
const SAFE_TOKEN = /^[\w@+=:,./-]+$/;
|
|
@@ -607,12 +804,13 @@ const PREFIX_COLOR = {
|
|
|
607
804
|
/**
|
|
608
805
|
* Run the composed children and aggregate their exit codes.
|
|
609
806
|
*
|
|
610
|
-
* Sequential when the caller asks for it
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
*
|
|
807
|
+
* Sequential when the caller asks for it: a lone child gains nothing from the
|
|
808
|
+
* concurrently harness, and the writers of a `--fix` run (the oxlint child, and
|
|
809
|
+
* later the one ESLint child that fixes) are each spawned on their own so
|
|
810
|
+
* nothing is reading a file while one of them rewrites it. Otherwise every
|
|
811
|
+
* child runs at once. Either way all of them run to completion: an ordinary
|
|
812
|
+
* lint failure in one no longer kills its siblings, so the user keeps every
|
|
813
|
+
* result. The returned code is non-zero when any child exited non-zero.
|
|
616
814
|
*
|
|
617
815
|
* @param commands - The child commands to run.
|
|
618
816
|
* @param cwd - The working directory.
|
|
@@ -797,7 +995,7 @@ function composeEslintCommand(options, context) {
|
|
|
797
995
|
args.push("--no-warn-ignored", "--concurrency", String(context.concurrency));
|
|
798
996
|
if (options.cache && context.ci) args.push("--cache-strategy", "content");
|
|
799
997
|
if (options.agents) args.push("--format", context.agentsFormatterPath);
|
|
800
|
-
if (
|
|
998
|
+
if (context.fix) args.push("--fix");
|
|
801
999
|
args.push(...options.eslintArgs, ...context.paths);
|
|
802
1000
|
return {
|
|
803
1001
|
args,
|
|
@@ -837,6 +1035,7 @@ function composePasses(passes, runPlan, options) {
|
|
|
837
1035
|
ci: runPlan.ci,
|
|
838
1036
|
concurrency: pass.concurrency,
|
|
839
1037
|
eslintLabel: pass.descriptor.label,
|
|
1038
|
+
fix: false,
|
|
840
1039
|
paths: options.paths,
|
|
841
1040
|
typeAwareEnv: pass.descriptor.typeAwareEnv
|
|
842
1041
|
}));
|
|
@@ -871,150 +1070,6 @@ function compose(runPlan, options) {
|
|
|
871
1070
|
notice: notices.length > 0 ? notices.join("") : void 0
|
|
872
1071
|
};
|
|
873
1072
|
}
|
|
874
|
-
//#endregion
|
|
875
|
-
//#region src/lint-cli/lib/state.ts
|
|
876
|
-
/**
|
|
877
|
-
* Directory (relative to the project root) where the CLI keeps its persisted
|
|
878
|
-
* state. Lives under `node_modules/.cache` so it is discarded with the
|
|
879
|
-
* dependency tree and never committed.
|
|
880
|
-
*/
|
|
881
|
-
const CACHE_DIRECTORY = path.join("node_modules", ".cache", "isentinel-lint");
|
|
882
|
-
/**
|
|
883
|
-
* The directory every state file lives in.
|
|
884
|
-
*
|
|
885
|
-
* @param cwd - The consumer project root.
|
|
886
|
-
* @returns The absolute path to the runner's cache directory.
|
|
887
|
-
*/
|
|
888
|
-
function stateDirectory(cwd) {
|
|
889
|
-
return path.resolve(cwd, CACHE_DIRECTORY);
|
|
890
|
-
}
|
|
891
|
-
/**
|
|
892
|
-
* Resolve one state file inside {@link stateDirectory}.
|
|
893
|
-
*
|
|
894
|
-
* @param cwd - The consumer project root.
|
|
895
|
-
* @param name - The state's base name.
|
|
896
|
-
* @param parts - Further hyphen-joined segments, usually the config-variant key
|
|
897
|
-
* from `resolveCacheKey`. State that is consumed once (a stored hash, a
|
|
898
|
-
* drained builder) must carry that key, or the first variant to run absorbs
|
|
899
|
-
* the change on behalf of all of them.
|
|
900
|
-
* @returns The absolute path to the state file.
|
|
901
|
-
*/
|
|
902
|
-
function statePath(cwd, name, ...parts) {
|
|
903
|
-
return path.join(stateDirectory(cwd), [name, ...parts].join("-"));
|
|
904
|
-
}
|
|
905
|
-
/**
|
|
906
|
-
* Read a UTF-8 file, or `undefined` when it cannot be read for any reason.
|
|
907
|
-
* Shared by every tolerant read in the CLI: state files, and the config-import
|
|
908
|
-
* closure walk.
|
|
909
|
-
*
|
|
910
|
-
* @param filePath - The file to read.
|
|
911
|
-
* @returns The file's content, or `undefined`.
|
|
912
|
-
*/
|
|
913
|
-
function readFileIfPresent(filePath) {
|
|
914
|
-
try {
|
|
915
|
-
return fs.readFileSync(filePath, "utf8");
|
|
916
|
-
} catch {
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
/**
|
|
921
|
-
* Read a state file written by {@link writeState}. Every failure mode — the
|
|
922
|
-
* file is missing, unreadable, malformed, or was written by another
|
|
923
|
-
* {@link STATE_VERSION} — degrades to `undefined`, which every caller treats as
|
|
924
|
-
* "unknown" and recomputes from.
|
|
925
|
-
*
|
|
926
|
-
* @template T - The shape this file's writer stores. Asserted, not checked:
|
|
927
|
-
* only the schema version is verified, exactly as the per-module casts this
|
|
928
|
-
* replaced did.
|
|
929
|
-
* @param filePath - The state file, from {@link statePath}.
|
|
930
|
-
* @returns The stored payload, or `undefined`.
|
|
931
|
-
*/
|
|
932
|
-
function readState(filePath) {
|
|
933
|
-
const raw = readFileIfPresent(filePath);
|
|
934
|
-
return raw === void 0 ? void 0 : parseState(raw);
|
|
935
|
-
}
|
|
936
|
-
/**
|
|
937
|
-
* Persist a state payload, creating the cache directory as needed.
|
|
938
|
-
*
|
|
939
|
-
* The write is atomic (temp file plus rename), since `plan()` runs concurrently
|
|
940
|
-
* across packages in a parallel per-package lint setup and a torn file would be
|
|
941
|
-
* read back as "unknown" at best.
|
|
942
|
-
*
|
|
943
|
-
* Best-effort — a failed write leaves the state unknown, so the next run
|
|
944
|
-
* recomputes rather than trusting something stale.
|
|
945
|
-
*
|
|
946
|
-
* @param filePath - The state file, from {@link statePath}.
|
|
947
|
-
* @param data - The payload to store.
|
|
948
|
-
*/
|
|
949
|
-
function writeState(filePath, data) {
|
|
950
|
-
const content = `${JSON.stringify({
|
|
951
|
-
data,
|
|
952
|
-
version: 2
|
|
953
|
-
})}\n`;
|
|
954
|
-
const temporary = `${filePath}.${process$1.pid}.tmp`;
|
|
955
|
-
try {
|
|
956
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
957
|
-
fs.writeFileSync(temporary, content);
|
|
958
|
-
fs.renameSync(temporary, filePath);
|
|
959
|
-
} catch {
|
|
960
|
-
try {
|
|
961
|
-
fs.rmSync(temporary, { force: true });
|
|
962
|
-
} catch {}
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
/**
|
|
966
|
-
* Compare a value against the stored one and replace it when they differ, the
|
|
967
|
-
* compare-and-swap every hash-drift bust runs: the caller acts on the outcome
|
|
968
|
-
* and never on the stored value itself.
|
|
969
|
-
*
|
|
970
|
-
* The value is consumed by the swap — once stored, every later run reads back
|
|
971
|
-
* `"unchanged"` — which is why hash state is keyed per config variant.
|
|
972
|
-
*
|
|
973
|
-
* A stored value this {@link STATE_VERSION} cannot read counts as `"changed"`,
|
|
974
|
-
* so a CLI upgrade invalidates rather than silently adopts what it finds.
|
|
975
|
-
*
|
|
976
|
-
* @param filePath - The state file, from {@link statePath}.
|
|
977
|
-
* @param value - The value this run computed.
|
|
978
|
-
* @returns How the stored value compared.
|
|
979
|
-
*/
|
|
980
|
-
function swapState(filePath, value) {
|
|
981
|
-
const raw = readFileIfPresent(filePath);
|
|
982
|
-
if ((raw === void 0 ? void 0 : parseState(raw)) === value) return "unchanged";
|
|
983
|
-
writeState(filePath, value);
|
|
984
|
-
return raw === void 0 ? "first" : "changed";
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* Refresh a state file's mtime without rewriting it, so a reader comparing that
|
|
988
|
-
* mtime against another file's still sees the state as fresh. Best-effort: a
|
|
989
|
-
* missing file simply stays missing.
|
|
990
|
-
*
|
|
991
|
-
* @param filePath - The state file, from {@link statePath}.
|
|
992
|
-
*/
|
|
993
|
-
function touchState(filePath) {
|
|
994
|
-
try {
|
|
995
|
-
const now = Date.now() / 1e3;
|
|
996
|
-
fs.utimesSync(filePath, now, now);
|
|
997
|
-
} catch {}
|
|
998
|
-
}
|
|
999
|
-
/**
|
|
1000
|
-
* Parse one state file's content, or `undefined` when it is malformed or
|
|
1001
|
-
* carries another {@link STATE_VERSION}.
|
|
1002
|
-
*
|
|
1003
|
-
* @template T - The shape this file's writer stores (asserted, not checked).
|
|
1004
|
-
* @param raw - The file's content.
|
|
1005
|
-
* @returns The stored payload, or `undefined`.
|
|
1006
|
-
*/
|
|
1007
|
-
function parseState(raw) {
|
|
1008
|
-
let parsed;
|
|
1009
|
-
try {
|
|
1010
|
-
parsed = JSON.parse(raw);
|
|
1011
|
-
} catch {
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
if (typeof parsed !== "object" || parsed === null) return;
|
|
1015
|
-
const envelope = parsed;
|
|
1016
|
-
return envelope.version === 2 ? envelope.data : void 0;
|
|
1017
|
-
}
|
|
1018
1073
|
/**
|
|
1019
1074
|
* Base name of every ESLint cache file the runner manages. Each real file adds
|
|
1020
1075
|
* a pass suffix and a config-variant key (see {@link cacheFileFor}), so this
|
|
@@ -1303,6 +1358,7 @@ function toPosix(value) {
|
|
|
1303
1358
|
}
|
|
1304
1359
|
//#endregion
|
|
1305
1360
|
//#region src/lint-cli/lib/cache/entries.ts
|
|
1361
|
+
const CASE_INSENSITIVE_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "win32"]);
|
|
1306
1362
|
/**
|
|
1307
1363
|
* Compute the newest modification time across the given files. Callers hash the
|
|
1308
1364
|
* cache-bust set once per run and compare each pass's cache mtime against the
|
|
@@ -1359,22 +1415,32 @@ function sweepStaleCaches(cwd, newestBustMtimeMs) {
|
|
|
1359
1415
|
return removed;
|
|
1360
1416
|
}
|
|
1361
1417
|
/**
|
|
1362
|
-
* Normalize a path for cache-key comparison: absolute
|
|
1363
|
-
* lower-cased
|
|
1364
|
-
*
|
|
1418
|
+
* Normalize a path for cache-key comparison: absolute and forward-slash, plus
|
|
1419
|
+
* lower-cased where the platform's filesystem is case-insensitive. TypeScript
|
|
1420
|
+
* emits forward-slash paths while ESLint keys the cache with OS-native ones,
|
|
1421
|
+
* and Windows and macOS reach the same file under either case — this collapses
|
|
1365
1422
|
* all of those into a single comparable form.
|
|
1366
1423
|
*
|
|
1424
|
+
* Case survives everywhere else: on a case-sensitive filesystem `src/Foo.ts`
|
|
1425
|
+
* and `src/foo.ts` are two files with two cache entries, and folding them
|
|
1426
|
+
* together would let one shadow the other's verdict.
|
|
1427
|
+
*
|
|
1367
1428
|
* @param filePath - The path to normalize.
|
|
1429
|
+
* @param platform - The platform whose filesystem the paths live on.
|
|
1368
1430
|
* @returns The canonical key.
|
|
1369
1431
|
*/
|
|
1370
|
-
function normalizePath(filePath) {
|
|
1371
|
-
|
|
1432
|
+
function normalizePath(filePath, platform = process$1.platform) {
|
|
1433
|
+
const resolved = toPosix(path.resolve(filePath));
|
|
1434
|
+
return CASE_INSENSITIVE_PLATFORMS.has(platform) ? resolved.toLowerCase() : resolved;
|
|
1372
1435
|
}
|
|
1373
1436
|
/**
|
|
1374
1437
|
* Open an ESLint cache for reuse, or `undefined` when the file is missing (the
|
|
1375
|
-
* caller then treats every target file as dirty).
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1438
|
+
* caller then treats every target file as dirty).
|
|
1439
|
+
*
|
|
1440
|
+
* The two reads share one parsed handle. The removal parses its own, because
|
|
1441
|
+
* asking a cache which files changed restamps every entry it looked at with
|
|
1442
|
+
* that file's current size and mtime: persisting that handle would hand ESLint
|
|
1443
|
+
* the previous run's results under a stamp saying they are current.
|
|
1378
1444
|
*
|
|
1379
1445
|
* @param cacheFilePath - The ESLint cache file to open.
|
|
1380
1446
|
* @param useChecksum - Compare by content checksum instead of metadata.
|
|
@@ -1382,10 +1448,11 @@ function normalizePath(filePath) {
|
|
|
1382
1448
|
*/
|
|
1383
1449
|
function openCache(cacheFilePath, useChecksum) {
|
|
1384
1450
|
if (!fs.existsSync(cacheFilePath)) return;
|
|
1385
|
-
const cache =
|
|
1451
|
+
const cache = load(cacheFilePath, useChecksum);
|
|
1386
1452
|
return {
|
|
1453
|
+
filesWithMessages: (files) => filesWithMessagesIn(cache, files),
|
|
1387
1454
|
getUpdatedFiles: (files) => cache.getUpdatedFiles(files),
|
|
1388
|
-
removeEntries: (files) => removeEntriesFrom(
|
|
1455
|
+
removeEntries: (files) => removeEntriesFrom(load(cacheFilePath, useChecksum), files)
|
|
1389
1456
|
};
|
|
1390
1457
|
}
|
|
1391
1458
|
function safeMtimeMs(filePath) {
|
|
@@ -1418,9 +1485,45 @@ function removeCacheFile(cacheFilePath) {
|
|
|
1418
1485
|
fs.rmSync(cacheFilePath, { force: true });
|
|
1419
1486
|
} catch {}
|
|
1420
1487
|
}
|
|
1421
|
-
|
|
1488
|
+
/**
|
|
1489
|
+
* Load a cache file the way ESLint's own `LintResultCache` does. The two read
|
|
1490
|
+
* and write the same entries, and a reader whose change detection disagrees
|
|
1491
|
+
* with the writer's reports every file as dirty.
|
|
1492
|
+
*
|
|
1493
|
+
* @param cacheFilePath - The ESLint cache file to load.
|
|
1494
|
+
* @param useChecksum - Compare by content checksum instead of metadata.
|
|
1495
|
+
* @returns The loaded cache.
|
|
1496
|
+
*/
|
|
1497
|
+
function load(cacheFilePath, useChecksum) {
|
|
1498
|
+
return fileEntryCache.createFromFile(cacheFilePath, {
|
|
1499
|
+
useCheckSum: useChecksum,
|
|
1500
|
+
useModifiedTime: !useChecksum
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Index a cache's entry keys by their normalized form, so a caller holding
|
|
1505
|
+
* paths from elsewhere — TypeScript's forward slashes, a git listing — can find
|
|
1506
|
+
* the entry ESLint wrote under an OS-native path.
|
|
1507
|
+
*
|
|
1508
|
+
* @param cache - The loaded cache to index.
|
|
1509
|
+
* @returns Normalized path to the key the cache stores it under.
|
|
1510
|
+
*/
|
|
1511
|
+
function keysByNormalizedPath(cache) {
|
|
1422
1512
|
const keyByNormalized = /* @__PURE__ */ new Map();
|
|
1423
1513
|
for (const key of cache.cache.keys()) keyByNormalized.set(normalizePath(key), key);
|
|
1514
|
+
return keyByNormalized;
|
|
1515
|
+
}
|
|
1516
|
+
function filesWithMessagesIn(cache, files) {
|
|
1517
|
+
const keyByNormalized = keysByNormalizedPath(cache);
|
|
1518
|
+
return files.filter((file) => {
|
|
1519
|
+
const key = keyByNormalized.get(normalizePath(file));
|
|
1520
|
+
if (key === void 0) return false;
|
|
1521
|
+
const messages = cache.cache.getKey(key)?.data?.results?.messages;
|
|
1522
|
+
return messages !== void 0 && messages.length > 0;
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
function removeEntriesFrom(cache, files) {
|
|
1526
|
+
const keyByNormalized = keysByNormalizedPath(cache);
|
|
1424
1527
|
let removed = 0;
|
|
1425
1528
|
for (const file of files) {
|
|
1426
1529
|
const key = keyByNormalized.get(normalizePath(file));
|
|
@@ -1429,7 +1532,7 @@ function removeEntriesFrom(cache, files) {
|
|
|
1429
1532
|
removed += 1;
|
|
1430
1533
|
}
|
|
1431
1534
|
}
|
|
1432
|
-
if (removed > 0) cache.cache.save(
|
|
1535
|
+
if (removed > 0) cache.cache.save();
|
|
1433
1536
|
return removed;
|
|
1434
1537
|
}
|
|
1435
1538
|
//#endregion
|
|
@@ -3699,7 +3802,9 @@ function collectRepoFiles(cwd, targets) {
|
|
|
3699
3802
|
const relatives = listFiles(cwd, ["."]);
|
|
3700
3803
|
const isBustFile = (0, import_picomatch.default)([...CACHE_BUST_PATTERNS], { dot: true });
|
|
3701
3804
|
const normalizedTargets = targets.map((target) => normalizeTarget(target, cwd));
|
|
3702
|
-
const
|
|
3805
|
+
const outsideCwdTargets = targets.filter((target) => {
|
|
3806
|
+
return isOutsideCwd(normalizeTarget(target, cwd));
|
|
3807
|
+
});
|
|
3703
3808
|
const isWithinTargets = matchTargets(normalizedTargets);
|
|
3704
3809
|
const bustFiles = collectAncestorBustFiles(cwd);
|
|
3705
3810
|
const lintable = [];
|
|
@@ -3716,7 +3821,7 @@ function collectRepoFiles(cwd, targets) {
|
|
|
3716
3821
|
bustFiles,
|
|
3717
3822
|
configFiles: bustFiles.filter(isConfigEntryPoint),
|
|
3718
3823
|
lintable,
|
|
3719
|
-
|
|
3824
|
+
outsideCwdTargets,
|
|
3720
3825
|
typeAware
|
|
3721
3826
|
};
|
|
3722
3827
|
}
|
|
@@ -3974,12 +4079,6 @@ function gitIgnoredTargets(cwd, targets) {
|
|
|
3974
4079
|
* failure this feature cannot have.
|
|
3975
4080
|
*/
|
|
3976
4081
|
/**
|
|
3977
|
-
* A synthetic basename for `createRequire`, which resolves relative to a file
|
|
3978
|
-
* rather than a directory. Spelled so it can never collide with a real consumer
|
|
3979
|
-
* module.
|
|
3980
|
-
*/
|
|
3981
|
-
const RESOLVE_ANCHOR = "__isentinel-lint__.js";
|
|
3982
|
-
/**
|
|
3983
4082
|
* Resolve the ESLint the consumer's config will be linted with: their own,
|
|
3984
4083
|
* resolved from `cwd`, falling back to the one resolvable from this file (the
|
|
3985
4084
|
* hoisted peer dependency) when `cwd` has no `node_modules` of its own — the
|
|
@@ -4528,7 +4627,10 @@ const TYPED_PASS = {
|
|
|
4528
4627
|
typeAwareEnv: "only",
|
|
4529
4628
|
typeAwareOnly: true
|
|
4530
4629
|
};
|
|
4531
|
-
/**
|
|
4630
|
+
/**
|
|
4631
|
+
* The full-config pass (env unset, `.eslintcache`): CI, `=full`, and the child
|
|
4632
|
+
* a `--fix` run spawns over the files its checks reported (see `planFixChild`).
|
|
4633
|
+
*/
|
|
4532
4634
|
const FULL_PASS = {
|
|
4533
4635
|
cacheFileBase: CACHE_FILE_DEFAULT,
|
|
4534
4636
|
filesPerWorker: (limits) => limits.filesPerWorker,
|
|
@@ -4539,19 +4641,23 @@ const FULL_PASS = {
|
|
|
4539
4641
|
};
|
|
4540
4642
|
/**
|
|
4541
4643
|
* Select the ESLint passes for the resolved mode. An explicit `--type-aware`
|
|
4542
|
-
* always wins: `=full`
|
|
4543
|
-
*
|
|
4544
|
-
*
|
|
4545
|
-
*
|
|
4546
|
-
*
|
|
4547
|
-
*
|
|
4644
|
+
* always wins: `=full` collapses to the single full pass, while `=off`/`=only`
|
|
4645
|
+
* run their one pass even in CI. Only when no mode is given does CI change the
|
|
4646
|
+
* default — collapsing the concurrent two-pass split to one full pass; a local
|
|
4647
|
+
* default run keeps the split (the typed pass may later be skipped). CI's
|
|
4648
|
+
* `--cache-strategy content` is applied by the command composer to whichever
|
|
4649
|
+
* pass runs, independently of this selection.
|
|
4650
|
+
*
|
|
4651
|
+
* `--fix` selects nothing of its own. Its ESLint children are the same checks
|
|
4652
|
+
* any other run has, and the fix itself is one further child composed from what
|
|
4653
|
+
* they reported (see `planFixChild`), which is why the checks stay concurrent.
|
|
4548
4654
|
*
|
|
4549
4655
|
* @param options - The parsed CLI options.
|
|
4550
4656
|
* @param ci - Whether the run is in CI.
|
|
4551
4657
|
* @returns The pass descriptors to plan, in run order.
|
|
4552
4658
|
*/
|
|
4553
4659
|
function selectPasses(options, ci) {
|
|
4554
|
-
if (options.
|
|
4660
|
+
if (options.typeAware === "full") return [FULL_PASS];
|
|
4555
4661
|
if (options.typeAware === "off") return [FAST_PASS];
|
|
4556
4662
|
if (options.typeAware === "only") return [TYPED_PASS];
|
|
4557
4663
|
if (ci) return [FULL_PASS];
|
|
@@ -4571,6 +4677,94 @@ function maxWorkersFor(descriptor, limits) {
|
|
|
4571
4677
|
return descriptor.invalidation === "none" ? limits.maxWorkers : limits.typedMaxWorkers;
|
|
4572
4678
|
}
|
|
4573
4679
|
//#endregion
|
|
4680
|
+
//#region src/lint-cli/lib/plan/fix.ts
|
|
4681
|
+
/**
|
|
4682
|
+
* The files the check passes had a message about, in pass order and without
|
|
4683
|
+
* duplicates.
|
|
4684
|
+
*
|
|
4685
|
+
* Read out of each pass's own cache rather than out of its output. ESLint
|
|
4686
|
+
* stores the lint result beside every entry and replays it on a cache hit, so
|
|
4687
|
+
* the cache is the pass's whole-tree verdict whichever files it actually
|
|
4688
|
+
* re-linted this run — including for a pass that auto-skipped, whose verdict
|
|
4689
|
+
* stands precisely because nothing it cares about changed.
|
|
4690
|
+
*
|
|
4691
|
+
* Each pass only contributes the targets it lints: the type-aware pass never
|
|
4692
|
+
* sees the JSON and Markdown the fast pass covers.
|
|
4693
|
+
*
|
|
4694
|
+
* @param passes - The planned passes, run and auto-skipped alike.
|
|
4695
|
+
* @param run - The run context.
|
|
4696
|
+
* @param files - The lint-target lists to look the verdict up against.
|
|
4697
|
+
* @returns The reported files, empty when every pass came back clean.
|
|
4698
|
+
*/
|
|
4699
|
+
function collectFixTargets(passes, run, files) {
|
|
4700
|
+
const targets = /* @__PURE__ */ new Set();
|
|
4701
|
+
for (const pass of passes) {
|
|
4702
|
+
const cache = openCache(path.resolve(run.cwd, pass.cacheFile), run.ci);
|
|
4703
|
+
const candidates = pass.descriptor.typeAwareOnly ? files.typeAware : files.lintable;
|
|
4704
|
+
const reported = cache?.filesWithMessages(candidates) ?? [];
|
|
4705
|
+
for (const file of reported) targets.add(file);
|
|
4706
|
+
}
|
|
4707
|
+
return [...targets];
|
|
4708
|
+
}
|
|
4709
|
+
/**
|
|
4710
|
+
* Compose the one ESLint child a `--fix` run spawns after its checks, or
|
|
4711
|
+
* `undefined` when they reported nothing and there is nothing to fix.
|
|
4712
|
+
*
|
|
4713
|
+
* The child runs the full config — a superset of both check configs, so it can
|
|
4714
|
+
* fix anything either of them found — over only the reported files. Being one
|
|
4715
|
+
* child, it is also the run's only ESLint writer.
|
|
4716
|
+
*
|
|
4717
|
+
* Its cache entries for those files are dropped first. The full config's cache
|
|
4718
|
+
* gets none of the invalidation the check caches do (no builder runs against
|
|
4719
|
+
* it), so it can hold a stale clean entry for a file the checks have since
|
|
4720
|
+
* found a message on, and ESLint would skip the very file it was handed.
|
|
4721
|
+
*
|
|
4722
|
+
* The child's targets are the union of what the verdicts cover and what they
|
|
4723
|
+
* cannot. `--no-cache` records no verdict at all, so the whole run falls back
|
|
4724
|
+
* to its own paths — the whole tree, as a fix run always used to lint. An
|
|
4725
|
+
* out-of-cwd target is invisible to the cwd-relative listing the verdicts are
|
|
4726
|
+
* looked up against (see {@link RepoFiles.outsideCwdTargets}), so it is passed
|
|
4727
|
+
* through as it stands while every in-cwd file stays narrowed to what the
|
|
4728
|
+
* checks reported.
|
|
4729
|
+
*
|
|
4730
|
+
* A raw path names no file whose cache entry can be dropped, so a child
|
|
4731
|
+
* carrying one runs without the cache rather than risk a stale clean entry
|
|
4732
|
+
* making ESLint skip it. That costs only the write: the covered files' entries
|
|
4733
|
+
* have just been dropped, so the cache would have saved that child no linting
|
|
4734
|
+
* anyway.
|
|
4735
|
+
*
|
|
4736
|
+
* @param passes - The planned passes whose verdicts narrow the child.
|
|
4737
|
+
* @param run - The run context.
|
|
4738
|
+
* @param inputs - The lint-target lists, CLI options, limits and formatter path.
|
|
4739
|
+
* @returns The fix child, or `undefined` when nothing was reported.
|
|
4740
|
+
*/
|
|
4741
|
+
function planFixChild(passes, run, inputs) {
|
|
4742
|
+
const { files, limits, options } = inputs;
|
|
4743
|
+
const covered = options.cache ? collectFixTargets(passes, run, files) : [];
|
|
4744
|
+
const uncovered = options.cache ? files.outsideCwdTargets : options.paths;
|
|
4745
|
+
const targets = [...covered, ...uncovered];
|
|
4746
|
+
if (targets.length === 0) return;
|
|
4747
|
+
const cacheFile = cacheFileFor(CACHE_FILE_DEFAULT, run.key);
|
|
4748
|
+
if (covered.length > 0) openCache(path.resolve(run.cwd, cacheFile), run.ci)?.removeEntries(covered);
|
|
4749
|
+
return composeEslintCommand({
|
|
4750
|
+
...options,
|
|
4751
|
+
cache: options.cache && uncovered.length === 0
|
|
4752
|
+
}, {
|
|
4753
|
+
agentsFormatterPath: inputs.agentsFormatterPath,
|
|
4754
|
+
cacheLocation: cacheFile,
|
|
4755
|
+
ci: run.ci,
|
|
4756
|
+
concurrency: options.concurrency ?? computeWorkerCount({
|
|
4757
|
+
dirtyCount: targets.length,
|
|
4758
|
+
filesPerWorker: limits.filesPerWorker,
|
|
4759
|
+
maxWorkers: limits.typedMaxWorkers
|
|
4760
|
+
}),
|
|
4761
|
+
eslintLabel: FULL_PASS.label,
|
|
4762
|
+
fix: true,
|
|
4763
|
+
paths: targets,
|
|
4764
|
+
typeAwareEnv: FULL_PASS.typeAwareEnv
|
|
4765
|
+
});
|
|
4766
|
+
}
|
|
4767
|
+
//#endregion
|
|
4574
4768
|
//#region src/lint-cli/lib/typescript/buildinfo.ts
|
|
4575
4769
|
/**
|
|
4576
4770
|
* Whether the program described by an existing `.tsbuildinfo` is exactly the
|
|
@@ -5405,7 +5599,7 @@ function passDirtyCount(descriptor, cacheFile, context) {
|
|
|
5405
5599
|
function sizePass(descriptor, context) {
|
|
5406
5600
|
const cacheFile = cacheFileFor(descriptor.cacheFileBase, context.run.key);
|
|
5407
5601
|
const dirtyCount = passDirtyCount(descriptor, cacheFile, context);
|
|
5408
|
-
const conservative = context.files.
|
|
5602
|
+
const conservative = context.files.outsideCwdTargets.length > 0;
|
|
5409
5603
|
const filesPerWorker = descriptor.filesPerWorker(context.limits, context.run.environment);
|
|
5410
5604
|
const maxWorkers = maxWorkersFor(descriptor, context.limits);
|
|
5411
5605
|
const sizingDirtyCount = conservative ? maxWorkers * filesPerWorker : dirtyCount;
|
|
@@ -5465,7 +5659,8 @@ function plan(options, run) {
|
|
|
5465
5659
|
passes: [],
|
|
5466
5660
|
targetsOutsideCwd: false
|
|
5467
5661
|
},
|
|
5468
|
-
resolveDeferred: void 0
|
|
5662
|
+
resolveDeferred: void 0,
|
|
5663
|
+
resolveFixChild: void 0
|
|
5469
5664
|
};
|
|
5470
5665
|
const descriptors = selectPasses(options, ci);
|
|
5471
5666
|
const files = collectRepoFiles(cwd, options.paths);
|
|
@@ -5495,10 +5690,11 @@ function plan(options, run) {
|
|
|
5495
5690
|
newestBustMtime,
|
|
5496
5691
|
options
|
|
5497
5692
|
};
|
|
5498
|
-
const
|
|
5693
|
+
const targetsOutsideCwd = files.outsideCwdTargets.length > 0;
|
|
5694
|
+
const staged = stageDescriptors(descriptors, run, {
|
|
5499
5695
|
multiPass: inputs.multiPass,
|
|
5500
|
-
oxlint: oxlintDecision.run,
|
|
5501
|
-
targetsOutsideCwd
|
|
5696
|
+
oxlint: oxlintDecision.run && !options.fix,
|
|
5697
|
+
targetsOutsideCwd
|
|
5502
5698
|
});
|
|
5503
5699
|
return {
|
|
5504
5700
|
eager: {
|
|
@@ -5509,9 +5705,17 @@ function plan(options, run) {
|
|
|
5509
5705
|
oxlintReason: oxlintDecision.reason,
|
|
5510
5706
|
oxlintTypeAware,
|
|
5511
5707
|
passes: sizePasses(staged.eager, run, inputs),
|
|
5512
|
-
targetsOutsideCwd
|
|
5708
|
+
targetsOutsideCwd
|
|
5513
5709
|
},
|
|
5514
|
-
resolveDeferred: staged.deferred.length > 0 ? () => sizePasses(staged.deferred, run, inputs) : void 0
|
|
5710
|
+
resolveDeferred: staged.deferred.length > 0 ? () => sizePasses(staged.deferred, run, inputs) : void 0,
|
|
5711
|
+
resolveFixChild: mutate && options.fix ? (passes) => {
|
|
5712
|
+
return planFixChild(passes, run, {
|
|
5713
|
+
agentsFormatterPath,
|
|
5714
|
+
files: sizingFiles,
|
|
5715
|
+
limits,
|
|
5716
|
+
options
|
|
5717
|
+
});
|
|
5718
|
+
} : void 0
|
|
5515
5719
|
};
|
|
5516
5720
|
}
|
|
5517
5721
|
function resolveOxlintTypeAware(options) {
|
|
@@ -5523,12 +5727,10 @@ function resolveOxlintTypeAware(options) {
|
|
|
5523
5727
|
* runs the TypeScript builder is ever held back — that is the whole cost being
|
|
5524
5728
|
* moved off the critical path.
|
|
5525
5729
|
*
|
|
5526
|
-
* Everything else stays eager, and
|
|
5730
|
+
* Everything else stays eager, and three cases opt out of staging entirely:
|
|
5527
5731
|
*
|
|
5528
5732
|
* - `--print` (`mutate` false) runs no builder anyway and must stay one pure
|
|
5529
5733
|
* snapshot printed in a single go;
|
|
5530
|
-
* - `--fix` runs its children one at a time, so a later spawn buys nothing and
|
|
5531
|
-
* there is no reason to reopen the write race the sequential path prevents;
|
|
5532
5734
|
* - a run with no eager child at all, where holding the builder-backed pass
|
|
5533
5735
|
* back would only delay the whole run;
|
|
5534
5736
|
* - a run whose one eager child could end up alone, because the type-aware pass
|
|
@@ -5537,19 +5739,18 @@ function resolveOxlintTypeAware(options) {
|
|
|
5537
5739
|
* prefixed, piped harness for no gain.
|
|
5538
5740
|
*
|
|
5539
5741
|
* @param descriptors - The selected passes, in run order.
|
|
5540
|
-
* @param options - The parsed CLI options.
|
|
5541
5742
|
* @param run - The run context.
|
|
5542
5743
|
* @param staging - The oxlint decision and the auto-skip inputs.
|
|
5543
5744
|
* @returns The two stages, each in run order.
|
|
5544
5745
|
*/
|
|
5545
|
-
function stageDescriptors(descriptors,
|
|
5746
|
+
function stageDescriptors(descriptors, run, staging) {
|
|
5546
5747
|
const eager = descriptors.filter((descriptor) => descriptor.invalidation === "none");
|
|
5547
5748
|
const deferred = descriptors.filter((descriptor) => descriptor.invalidation !== "none");
|
|
5548
5749
|
const unstaged = {
|
|
5549
5750
|
deferred: [],
|
|
5550
5751
|
eager: descriptors
|
|
5551
5752
|
};
|
|
5552
|
-
if (!run.mutate ||
|
|
5753
|
+
if (!run.mutate || deferred.length === 0) return unstaged;
|
|
5553
5754
|
const eagerChildren = (staging.oxlint ? 1 : 0) + eager.length;
|
|
5554
5755
|
const mayAutoSkip = staging.multiPass && !staging.targetsOutsideCwd;
|
|
5555
5756
|
if (eagerChildren === 0 || eagerChildren === 1 && mayAutoSkip) return unstaged;
|
|
@@ -5579,13 +5780,47 @@ async function runLint(argv, cwd = process$1.cwd(), environment = process$1.env)
|
|
|
5579
5780
|
}
|
|
5580
5781
|
if (commands.some((command) => command.bin === "oxlint" && command.args.includes("--type-aware")) && !isPackageExists("oxlint-tsgolint", { paths: [cwd] })) throw new CliError("oxlint-tsgolint is not installed, so oxlint cannot run type-aware rules. Install oxlint-tsgolint, or pass --no-oxlint-type-aware to skip type-aware linting.");
|
|
5581
5782
|
if (notice !== void 0) process$1.stderr.write(notice);
|
|
5783
|
+
const { resolveFixChild } = staged;
|
|
5784
|
+
if (resolveFixChild === void 0) return (await runChecks(commands, cwd, staged, options)).code;
|
|
5785
|
+
const byBin = Object.groupBy(commands, (command) => command.bin);
|
|
5786
|
+
const oxlintCode = await execute(byBin.oxlint ?? [], cwd, true);
|
|
5787
|
+
const checks = await runChecks(byBin.eslint ?? [], cwd, staged, options);
|
|
5788
|
+
const fixChild = resolveFixChild(checks.passes);
|
|
5789
|
+
if (fixChild === void 0) return oxlintCode || checks.code;
|
|
5790
|
+
return oxlintCode || await execute([fixChild], cwd, true);
|
|
5791
|
+
}
|
|
5792
|
+
/**
|
|
5793
|
+
* Run a run's ESLint check children and report which passes they covered.
|
|
5794
|
+
*
|
|
5795
|
+
* A staged run is concurrent by construction (the planner only stages when at
|
|
5796
|
+
* least one other child is already linting). Its type-aware pass is planned —
|
|
5797
|
+
* TypeScript builder and all — only once the children above are running, and
|
|
5798
|
+
* its notice is emitted as soon as it is known rather than held to the end of
|
|
5799
|
+
* the run.
|
|
5800
|
+
*
|
|
5801
|
+
* @param commands - The composed check children.
|
|
5802
|
+
* @param cwd - The working directory.
|
|
5803
|
+
* @param staged - The staged plan the commands came from.
|
|
5804
|
+
* @param options - The parsed CLI options.
|
|
5805
|
+
* @returns The aggregated exit code and every pass that was planned.
|
|
5806
|
+
*/
|
|
5807
|
+
async function runChecks(commands, cwd, staged, options) {
|
|
5808
|
+
const passes = [...staged.eager.passes];
|
|
5582
5809
|
const { resolveDeferred } = staged;
|
|
5583
|
-
if (resolveDeferred === void 0) return
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5810
|
+
if (resolveDeferred === void 0) return {
|
|
5811
|
+
code: await execute(commands, cwd, commands.length <= 1),
|
|
5812
|
+
passes
|
|
5813
|
+
};
|
|
5814
|
+
return {
|
|
5815
|
+
code: await executeStaged(commands, cwd, () => {
|
|
5816
|
+
const deferred = resolveDeferred();
|
|
5817
|
+
passes.push(...deferred);
|
|
5818
|
+
const later = composePasses(deferred, staged.eager, options);
|
|
5819
|
+
if (later.notice !== void 0) process$1.stderr.write(later.notice);
|
|
5820
|
+
return later.commands;
|
|
5821
|
+
}),
|
|
5822
|
+
passes
|
|
5823
|
+
};
|
|
5589
5824
|
}
|
|
5590
5825
|
//#endregion
|
|
5591
5826
|
//#region src/lint-cli/index.ts
|
|
@@ -5597,7 +5832,8 @@ files actually need re-linting and managing per-mode caches.
|
|
|
5597
5832
|
Flags:
|
|
5598
5833
|
--eslint Run only ESLint.
|
|
5599
5834
|
--oxlint Run only oxlint.
|
|
5600
|
-
--fix
|
|
5835
|
+
--fix Check as usual, then fix only the files the checks
|
|
5836
|
+
reported, in one further ESLint child.
|
|
5601
5837
|
--agents, --no-agents Emit agent-friendly output. On by default when an AI
|
|
5602
5838
|
agent session is detected (AI_AGENT, CLAUDECODE, ...).
|
|
5603
5839
|
--type-aware=off|only|full
|
package/dist/lint-ignored.mjs
CHANGED
|
@@ -29,6 +29,14 @@ function isStringArray(value) {
|
|
|
29
29
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
30
30
|
}
|
|
31
31
|
//#endregion
|
|
32
|
+
//#region src/lint-cli/lib/exec/resolve.ts
|
|
33
|
+
/**
|
|
34
|
+
* A synthetic basename for `createRequire`, which resolves relative to a file
|
|
35
|
+
* rather than a directory. Spelled so it can never collide with a real consumer
|
|
36
|
+
* module.
|
|
37
|
+
*/
|
|
38
|
+
const RESOLVE_ANCHOR = "__isentinel-lint__.js";
|
|
39
|
+
//#endregion
|
|
32
40
|
//#region src/lint-cli/lib/exec/eslint-install.ts
|
|
33
41
|
/**
|
|
34
42
|
* Locating the ESLint installation a run's config is resolved against.
|
|
@@ -41,12 +49,6 @@ function isStringArray(value) {
|
|
|
41
49
|
* failure this feature cannot have.
|
|
42
50
|
*/
|
|
43
51
|
/**
|
|
44
|
-
* A synthetic basename for `createRequire`, which resolves relative to a file
|
|
45
|
-
* rather than a directory. Spelled so it can never collide with a real consumer
|
|
46
|
-
* module.
|
|
47
|
-
*/
|
|
48
|
-
const RESOLVE_ANCHOR = "__isentinel-lint__.js";
|
|
49
|
-
/**
|
|
50
52
|
* Resolve the ESLint the consumer's config will be linted with: their own,
|
|
51
53
|
* resolved from `cwd`, falling back to the one resolvable from this file (the
|
|
52
54
|
* hoisted peer dependency) when `cwd` has no `node_modules` of its own — the
|
package/dist/oxlint.d.mts
CHANGED
|
@@ -6660,7 +6660,7 @@ interface RuleOptions {
|
|
|
6660
6660
|
* Disallow unmodified loop conditions
|
|
6661
6661
|
* @see https://eslint.org/docs/latest/rules/no-unmodified-loop-condition
|
|
6662
6662
|
*/
|
|
6663
|
-
'no-unmodified-loop-condition'?: Linter.RuleEntry<
|
|
6663
|
+
'no-unmodified-loop-condition'?: Linter.RuleEntry<NoUnmodifiedLoopCondition>;
|
|
6664
6664
|
/**
|
|
6665
6665
|
* Disallow ternary operators when simpler alternatives exist
|
|
6666
6666
|
* @see https://eslint.org/docs/latest/rules/no-unneeded-ternary
|
|
@@ -16979,6 +16979,10 @@ type NoUnderscoreDangle = [] | [{
|
|
|
16979
16979
|
allowInArrayDestructuring?: boolean;
|
|
16980
16980
|
allowInObjectDestructuring?: boolean;
|
|
16981
16981
|
}];
|
|
16982
|
+
// ----- no-unmodified-loop-condition -----
|
|
16983
|
+
type NoUnmodifiedLoopCondition = [] | [{
|
|
16984
|
+
checkConditionalExpressions?: boolean;
|
|
16985
|
+
}];
|
|
16982
16986
|
// ----- no-unneeded-ternary -----
|
|
16983
16987
|
type NoUnneededTernary = [] | [{
|
|
16984
16988
|
defaultAssignment?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isentinel/eslint-config",
|
|
3
|
-
"version": "6.0.0-beta.
|
|
3
|
+
"version": "6.0.0-beta.46",
|
|
4
4
|
"description": "iSentinel's ESLint config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint-config",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"@types/yargs": "17.0.35",
|
|
123
123
|
"@vitest/eslint-plugin": "1.6.26",
|
|
124
124
|
"bumpp": "12.0.0",
|
|
125
|
-
"eslint": "10.
|
|
125
|
+
"eslint": "10.10.0",
|
|
126
126
|
"eslint-plugin-erasable-syntax-only": "0.4.2",
|
|
127
127
|
"eslint-plugin-eslint-plugin": "7.5.0",
|
|
128
128
|
"eslint-plugin-jest": "29.16.0",
|
|
@@ -145,11 +145,11 @@
|
|
|
145
145
|
"typescript": "6.0.3",
|
|
146
146
|
"unplugin-unused": "0.5.7",
|
|
147
147
|
"vitest": "4.1.10",
|
|
148
|
-
"@isentinel/eslint-config": "6.0.0-beta.
|
|
148
|
+
"@isentinel/eslint-config": "6.0.0-beta.46"
|
|
149
149
|
},
|
|
150
150
|
"peerDependencies": {
|
|
151
151
|
"@vitest/eslint-plugin": "^1.6.4",
|
|
152
|
-
"eslint": "^10.
|
|
152
|
+
"eslint": "^10.10.0",
|
|
153
153
|
"eslint-plugin-eslint-plugin": "^7.5.0",
|
|
154
154
|
"eslint-plugin-jest": "^29.15.0",
|
|
155
155
|
"eslint-plugin-jest-extended": "^3.0.0",
|