@isentinel/eslint-config 6.0.1 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.mjs +12 -3
- package/dist/lint-cli.mjs +294 -18
- package/dist/oxlint.d.mts +7 -2
- package/dist/oxlint.mjs +22 -16
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -253,6 +253,22 @@ Other behaviours:
|
|
|
253
253
|
re-lint (its own dirty count), rather than eagerly spinning up a worker per
|
|
254
254
|
CPU. The fast pass is cheap per file, so it packs far more files per worker
|
|
255
255
|
(see `FAST_FILES_PER_WORKER`) than the type-aware pass.
|
|
256
|
+
- Sizes the heap of every ESLint child that builds a TypeScript program (the
|
|
257
|
+
type-aware pass, the full pass and the fix child). Each worker holds its own
|
|
258
|
+
program, so the limit that matters is workers × heap. By default the runner
|
|
259
|
+
splits half the machine's memory (or its cgroup limit, when lower) across
|
|
260
|
+
those workers, and raises Node's heap limit when the share is larger. When the
|
|
261
|
+
budget cannot give each worker twice Node's default heap, it runs fewer
|
|
262
|
+
workers: every worker loads the program of nearly every project, so fewer,
|
|
263
|
+
larger workers need far less memory in total than more, smaller ones. The flag
|
|
264
|
+
goes in the child's `NODE_OPTIONS`, which every ESLint worker inherits; oxlint
|
|
265
|
+
and the fast pass never get it. `--print` shows the chosen workers, files per
|
|
266
|
+
worker and heap on stderr. If a child still runs out of memory, the runner
|
|
267
|
+
prints a hint that names `LINT_TYPED_HEAP_MB`. A size set in
|
|
268
|
+
`LINT_TYPED_HEAP_MB` also caps the workers at budget ÷ size. An explicit
|
|
269
|
+
`LINT_MAX_WORKERS` or `--concurrency` is never reduced. A
|
|
270
|
+
`--max-old-space-size` already in `NODE_OPTIONS` wins over all of this: the
|
|
271
|
+
runner adds nothing and keeps the worker count.
|
|
256
272
|
- Keeps a separate ESLint cache per pass so they never invalidate one another:
|
|
257
273
|
`.eslintcache-fast-<key>` (fast pass), `.eslintcache-typeaware-<key>`
|
|
258
274
|
(type-aware pass), and `.eslintcache-<key>` (the full config, used by CI,
|
|
@@ -394,6 +410,7 @@ or `--`.
|
|
|
394
410
|
| `FILES_PER_WORKER` | Target files a single type-aware ESLint worker handles before adding another (default `350`). |
|
|
395
411
|
| `FAST_FILES_PER_WORKER` | Same, for the fast (syntactic) pass, which packs far more files per worker (default `800`). |
|
|
396
412
|
| `LINT_MAX_WORKERS` | Upper bound on ESLint workers (default a quarter of available CPUs). |
|
|
413
|
+
| `LINT_TYPED_HEAP_MB` | Heap per worker for the program-building ESLint children: `auto` (default), a size in MB, or `off` (Node's default). |
|
|
397
414
|
| `ESLINT_TYPE_AWARE` | `off` or `only`; the type-aware mode `--type-aware` sets for the ESLint child (`false` is a legacy alias for `off`). |
|
|
398
415
|
| `CI` | When set, the runner uses the single full pass with `--cache-strategy content` (see below). |
|
|
399
416
|
|
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
|
|
12
|
+
var version = "6.1.0";
|
|
13
13
|
var package_default = {
|
|
14
14
|
name: "@isentinel/eslint-config",
|
|
15
15
|
version,
|
package/dist/index.d.mts
CHANGED
|
@@ -28502,7 +28502,14 @@ declare function loadSmallRulesPlugin(): NonNullable<TypedFlatConfigItem["plugin
|
|
|
28502
28502
|
declare function smallRules(options?: OptionsComponentExtensions & OptionsFiles & OptionsIsInEditor & OptionsStylistic): Array<TypedFlatConfigItem>;
|
|
28503
28503
|
//#endregion
|
|
28504
28504
|
//#region src/eslint/configs/sonarjs.d.ts
|
|
28505
|
-
declare function sonarjs({ isInEditor, roblox }: OptionsHasRoblox & Required<OptionsIsInEditor>
|
|
28505
|
+
declare function sonarjs({ complementIgnores, isInEditor, roblox }: OptionsHasRoblox & Required<OptionsIsInEditor> & {
|
|
28506
|
+
/**
|
|
28507
|
+
* When set, re-apply the non-roblox rules to every source file except
|
|
28508
|
+
* these globs (the roblox scope), so the complement is linted as
|
|
28509
|
+
* standard-TS/Node land.
|
|
28510
|
+
*/
|
|
28511
|
+
complementIgnores?: Array<string>;
|
|
28512
|
+
}): Promise<Array<TypedFlatConfigItem>>;
|
|
28506
28513
|
//#endregion
|
|
28507
28514
|
//#region src/eslint/configs/sort.d.ts
|
|
28508
28515
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -4523,7 +4523,8 @@ function sonarjsTestRules({ jest = false, roblox = true } = {}) {
|
|
|
4523
4523
|
}
|
|
4524
4524
|
//#endregion
|
|
4525
4525
|
//#region src/eslint/configs/sonarjs.ts
|
|
4526
|
-
|
|
4526
|
+
init_globs();
|
|
4527
|
+
async function sonarjs({ complementIgnores, isInEditor, roblox }) {
|
|
4527
4528
|
return [{
|
|
4528
4529
|
name: "isentinel/sonarjs",
|
|
4529
4530
|
plugins: { sonar: await interopDefault(import("eslint-plugin-sonarjs")) },
|
|
@@ -4531,7 +4532,15 @@ async function sonarjs({ isInEditor, roblox }) {
|
|
|
4531
4532
|
isInEditor,
|
|
4532
4533
|
roblox
|
|
4533
4534
|
})
|
|
4534
|
-
}
|
|
4535
|
+
}, ...complementIgnores ? [{
|
|
4536
|
+
name: "isentinel/sonarjs/complement",
|
|
4537
|
+
files: [GLOB_SRC],
|
|
4538
|
+
ignores: complementIgnores,
|
|
4539
|
+
rules: sonarjsRules({
|
|
4540
|
+
isInEditor,
|
|
4541
|
+
roblox: false
|
|
4542
|
+
})
|
|
4543
|
+
}] : []];
|
|
4535
4544
|
}
|
|
4536
4545
|
//#endregion
|
|
4537
4546
|
//#region src/eslint/configs/sort.ts
|
|
@@ -5938,7 +5947,6 @@ function typescriptTypeAwareRules({ roblox = true } = {}) {
|
|
|
5938
5947
|
"ts/no-confusing-void-expression": "error",
|
|
5939
5948
|
"ts/no-deprecated": "error",
|
|
5940
5949
|
"ts/no-duplicate-type-constituents": "error",
|
|
5941
|
-
"ts/no-empty-object-type": "error",
|
|
5942
5950
|
"ts/no-floating-promises": ["error", {
|
|
5943
5951
|
checkThenables: roblox,
|
|
5944
5952
|
ignoreVoid: true
|
|
@@ -20314,6 +20322,7 @@ async function isentinel(options, ...userConfigs) {
|
|
|
20314
20322
|
roblox: enableRoblox,
|
|
20315
20323
|
stylistic: stylisticOptions
|
|
20316
20324
|
}), promise(), sonarjs({
|
|
20325
|
+
...needsComplementOverlay ? { complementIgnores: robloxScopedFiles } : {},
|
|
20317
20326
|
isInEditor,
|
|
20318
20327
|
roblox: enableRoblox
|
|
20319
20328
|
}), typescript({
|
package/dist/lint-cli.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { KillOnSignal, LogError, LogExit, LogOutput, Logger, createConcurrently
|
|
|
14
14
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
15
15
|
import os, { availableParallelism } from "node:os";
|
|
16
16
|
import { Writable } from "node:stream";
|
|
17
|
+
import v8 from "node:v8";
|
|
17
18
|
import { fileURLToPath } from "node:url";
|
|
18
19
|
import fileEntryCache from "file-entry-cache";
|
|
19
20
|
//#region \0rolldown/runtime.js
|
|
@@ -40,7 +41,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
40
41
|
}) : target, mod));
|
|
41
42
|
//#endregion
|
|
42
43
|
//#region package.json
|
|
43
|
-
var version = "6.0
|
|
44
|
+
var version = "6.1.0";
|
|
44
45
|
//#endregion
|
|
45
46
|
//#region src/lint-cli/lib/cli/types.ts
|
|
46
47
|
/**
|
|
@@ -570,6 +571,188 @@ function resolveRunContext(cwd, environment, mutate) {
|
|
|
570
571
|
};
|
|
571
572
|
}
|
|
572
573
|
//#endregion
|
|
574
|
+
//#region src/lint-cli/lib/plan/heap.ts
|
|
575
|
+
/**
|
|
576
|
+
* Environment variable that sets the heap of a program-building ESLint child.
|
|
577
|
+
*/
|
|
578
|
+
const HEAP_ENV = "LINT_TYPED_HEAP_MB";
|
|
579
|
+
/**
|
|
580
|
+
* Share of the machine's memory the program-building workers may claim between
|
|
581
|
+
* them. The rest is left for the oxlint child, the fast pass, the editor and
|
|
582
|
+
* the OS, all of which run alongside the type-aware pass locally.
|
|
583
|
+
*/
|
|
584
|
+
const HEAP_BUDGET_SHARE = .5;
|
|
585
|
+
const BYTES_PER_MB = 1024 * 1024;
|
|
586
|
+
const MAX_OLD_SPACE = /--max[-_]old[-_]space[-_]size\b/;
|
|
587
|
+
/**
|
|
588
|
+
* Read the machine's memory facts.
|
|
589
|
+
*
|
|
590
|
+
* @returns The available memory and V8's default heap limit, in MB.
|
|
591
|
+
*/
|
|
592
|
+
function probeMemory() {
|
|
593
|
+
const total = os.totalmem();
|
|
594
|
+
const constrained = process$1.constrainedMemory();
|
|
595
|
+
return {
|
|
596
|
+
availableMb: Math.floor((constrained > 0 ? Math.min(total, constrained) : total) / BYTES_PER_MB),
|
|
597
|
+
defaultHeapMb: Math.floor(v8.getHeapStatistics().heap_size_limit / BYTES_PER_MB)
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Resolve the heap setting from the environment. An invalid {@link HEAP_ENV}
|
|
602
|
+
* falls back to `auto`, as the other numeric knobs fall back to their
|
|
603
|
+
* defaults.
|
|
604
|
+
*
|
|
605
|
+
* @param environment - Where {@link HEAP_ENV} and `NODE_OPTIONS` are read.
|
|
606
|
+
* @returns Which of the four modes applies, with its size when fixed.
|
|
607
|
+
*/
|
|
608
|
+
function resolveHeapSetting(environment) {
|
|
609
|
+
if (MAX_OLD_SPACE.test(environment["NODE_OPTIONS"] ?? "")) return { kind: "inherited" };
|
|
610
|
+
const raw = environment[HEAP_ENV]?.trim();
|
|
611
|
+
if (raw === "off") return { kind: "off" };
|
|
612
|
+
const mb = parseBoundedInteger(raw, 1);
|
|
613
|
+
return mb === void 0 ? { kind: "auto" } : {
|
|
614
|
+
kind: "fixed",
|
|
615
|
+
mb
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* The memory all program-building workers may claim together, in MB.
|
|
620
|
+
*
|
|
621
|
+
* @param memory - What the machine offers.
|
|
622
|
+
* @returns The budget share of the available memory, in MB.
|
|
623
|
+
*/
|
|
624
|
+
function heapBudgetMb(memory) {
|
|
625
|
+
return Math.floor(memory.availableMb * HEAP_BUDGET_SHARE);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* The most program-building workers the budget can hold, or `undefined` when
|
|
629
|
+
* the setting places no limit. Each worker is counted at the heap it may grow
|
|
630
|
+
* to: the requested size, or {@link AUTO_HEAP_FLOOR} times Node's default
|
|
631
|
+
* under `auto`. Never below one.
|
|
632
|
+
*
|
|
633
|
+
* @param budget - The setting and the machine it applies to.
|
|
634
|
+
* @returns How many workers fit, if the setting limits them.
|
|
635
|
+
*/
|
|
636
|
+
function heapWorkerCap({ memory, setting }) {
|
|
637
|
+
if (setting.kind !== "auto" && setting.kind !== "fixed") return;
|
|
638
|
+
const perWorker = setting.kind === "fixed" ? setting.mb : memory.defaultHeapMb * 2;
|
|
639
|
+
return Math.max(1, Math.floor(heapBudgetMb(memory) / perWorker));
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* The heap each worker of a program-building pass gets, or `undefined` for
|
|
643
|
+
* Node's default. `auto` splits the budget across the workers and only raises
|
|
644
|
+
* the limit: a share below the default adds no flag.
|
|
645
|
+
*
|
|
646
|
+
* @param budget - The setting and the machine it applies to.
|
|
647
|
+
* @param concurrency - The pass's resolved concurrency (`off` lints on the
|
|
648
|
+
* main thread, which is one heap).
|
|
649
|
+
* @returns The size in MB to pass to Node, if it should change.
|
|
650
|
+
*/
|
|
651
|
+
function heapPerWorkerMb({ memory, setting }, concurrency) {
|
|
652
|
+
if (setting.kind === "fixed") return setting.mb;
|
|
653
|
+
if (setting.kind !== "auto") return;
|
|
654
|
+
const share = Math.floor(heapBudgetMb(memory) / workerCount(concurrency));
|
|
655
|
+
return share > memory.defaultHeapMb ? share : void 0;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Pair the run's heap setting with the machine it applies to.
|
|
659
|
+
*
|
|
660
|
+
* @param environment - Where {@link HEAP_ENV} and `NODE_OPTIONS` are read.
|
|
661
|
+
* @param memory - What the machine offers.
|
|
662
|
+
* @returns Everything sizing needs to give a program-building pass its heap.
|
|
663
|
+
*/
|
|
664
|
+
function resolveHeapBudget(environment, memory) {
|
|
665
|
+
return {
|
|
666
|
+
memory,
|
|
667
|
+
nodeOptions: environment["NODE_OPTIONS"],
|
|
668
|
+
setting: resolveHeapSetting(environment)
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* The worker cap of a program-building pass once the heap budget is applied.
|
|
673
|
+
* An explicit `LINT_MAX_WORKERS` is never tightened.
|
|
674
|
+
*
|
|
675
|
+
* @param maxWorkers - The pass's cap before the budget.
|
|
676
|
+
* @param explicit - Whether `LINT_MAX_WORKERS` set that cap.
|
|
677
|
+
* @param budget - The setting and the machine it applies to.
|
|
678
|
+
* @returns The cap to size the pass against.
|
|
679
|
+
*/
|
|
680
|
+
function capWorkersForHeap(maxWorkers, explicit, budget) {
|
|
681
|
+
const cap = explicit ? void 0 : heapWorkerCap(budget);
|
|
682
|
+
return cap === void 0 ? maxWorkers : Math.min(maxWorkers, cap);
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Plan the heap of one program-building child from its sizing.
|
|
686
|
+
*
|
|
687
|
+
* @param label - The child's label, for the `--print` line.
|
|
688
|
+
* @param budget - The setting and the machine it applies to.
|
|
689
|
+
* @param sizing - The child's concurrency and file count.
|
|
690
|
+
* @returns Its `NODE_OPTIONS`, its `--print` line and whether it is watched.
|
|
691
|
+
*/
|
|
692
|
+
function planPassHeap(label, budget, sizing) {
|
|
693
|
+
const heapMb = heapPerWorkerMb(budget, sizing.concurrency);
|
|
694
|
+
return {
|
|
695
|
+
nodeOptions: heapNodeOptions(budget, heapMb),
|
|
696
|
+
note: describeHeapPlan(label, budget, sizing, heapMb),
|
|
697
|
+
watch: budget.setting.kind !== "off"
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* The number of heaps a concurrency value runs: `off` lints on the main
|
|
702
|
+
* thread, which is one.
|
|
703
|
+
*
|
|
704
|
+
* @param concurrency - A resolved ESLint concurrency.
|
|
705
|
+
* @returns How many threads lint.
|
|
706
|
+
*/
|
|
707
|
+
function workerCount(concurrency) {
|
|
708
|
+
return concurrency === "off" ? 1 : concurrency;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* The `NODE_OPTIONS` a program-building child runs under: the inherited value
|
|
712
|
+
* with the heap flag appended. Node's `worker_threads` take their heap limit
|
|
713
|
+
* from `--max-old-space-size` when it is set, so this one flag reaches every
|
|
714
|
+
* ESLint worker.
|
|
715
|
+
*
|
|
716
|
+
* @param budget - Carries the inherited `NODE_OPTIONS`.
|
|
717
|
+
* @param heapMb - The size in MB for each worker, if it should change.
|
|
718
|
+
* @returns The value to set, or `undefined` to leave `NODE_OPTIONS` alone.
|
|
719
|
+
*/
|
|
720
|
+
function heapNodeOptions({ nodeOptions }, heapMb) {
|
|
721
|
+
if (heapMb === void 0) return;
|
|
722
|
+
const flag = `--max-old-space-size=${String(heapMb)}`;
|
|
723
|
+
const inherited = nodeOptions?.trim() ?? "";
|
|
724
|
+
return inherited.length > 0 ? `${inherited} ${flag}` : flag;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* How the `--print` line names a heap the runner left alone.
|
|
728
|
+
*
|
|
729
|
+
* @param budget - Says whether the user's `NODE_OPTIONS` set it.
|
|
730
|
+
* @returns The user's heap, or Node's default with its size.
|
|
731
|
+
*/
|
|
732
|
+
function unchangedHeap({ memory, setting }) {
|
|
733
|
+
return setting.kind === "inherited" ? "the NODE_OPTIONS heap" : `Node's default heap (${String(memory.defaultHeapMb)} MB)`;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Describe the memory plan of a program-building pass for `--print`.
|
|
737
|
+
*
|
|
738
|
+
* @param label - The pass's child label.
|
|
739
|
+
* @param budget - The setting and the machine it applies to.
|
|
740
|
+
* @param sizing - The pass's concurrency and file count.
|
|
741
|
+
* @param heapMb - The size given to each worker, if it changed.
|
|
742
|
+
* @returns One stderr line naming the workers, files per worker and heap.
|
|
743
|
+
*/
|
|
744
|
+
function describeHeapPlan(label, budget, { concurrency, dirtyCount }, heapMb) {
|
|
745
|
+
const workers = workerCount(concurrency);
|
|
746
|
+
const heap = heapMb === void 0 ? unchangedHeap(budget) : `${String(heapMb)} MB heap`;
|
|
747
|
+
const source = {
|
|
748
|
+
auto: `auto, budget ${String(heapBudgetMb(budget.memory))} MB`,
|
|
749
|
+
fixed: HEAP_ENV,
|
|
750
|
+
inherited: "NODE_OPTIONS",
|
|
751
|
+
off: `${HEAP_ENV}=off`
|
|
752
|
+
}[budget.setting.kind];
|
|
753
|
+
return `isentinel-lint: ${label} pass: ${String(workers)} worker(s), ~${String(Math.ceil(dirtyCount / workers))} files per worker, ${heap} per worker (${source}).\n`;
|
|
754
|
+
}
|
|
755
|
+
//#endregion
|
|
573
756
|
//#region src/lint-cli/lib/state.ts
|
|
574
757
|
/**
|
|
575
758
|
* Directory (relative to the project root) where the CLI keeps its persisted
|
|
@@ -848,6 +1031,11 @@ function resolveManifest(name, cwd) {
|
|
|
848
1031
|
}
|
|
849
1032
|
//#endregion
|
|
850
1033
|
//#region src/lint-cli/lib/exec/execute.ts
|
|
1034
|
+
/**
|
|
1035
|
+
* What V8 writes when a heap fills: `ERR_WORKER_OUT_OF_MEMORY` from a worker,
|
|
1036
|
+
* `JavaScript heap out of memory` from the main thread.
|
|
1037
|
+
*/
|
|
1038
|
+
const OUT_OF_MEMORY = /ERR_WORKER_OUT_OF_MEMORY|heap out of memory/;
|
|
851
1039
|
/** The signals that cancel a run, matching `concurrently`'s `KillOnSignal`. */
|
|
852
1040
|
const CANCEL_SIGNALS = [
|
|
853
1041
|
"SIGHUP",
|
|
@@ -877,6 +1065,17 @@ const PREFIX_COLOR = {
|
|
|
877
1065
|
typed: "cyan"
|
|
878
1066
|
};
|
|
879
1067
|
/**
|
|
1068
|
+
* The hint printed after a program-building child ran out of heap, below the
|
|
1069
|
+
* engine's own stack trace.
|
|
1070
|
+
*
|
|
1071
|
+
* @param label - The child's label.
|
|
1072
|
+
* @returns One stderr line.
|
|
1073
|
+
*/
|
|
1074
|
+
function outOfMemoryHint(label) {
|
|
1075
|
+
return `isentinel-lint: the ${label} ESLint pass ran out of memory. Set ${HEAP_ENV}=<mb> to give each worker more heap; the runner starts fewer workers to keep them in budget.
|
|
1076
|
+
`;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
880
1079
|
* Run the composed children and aggregate their exit codes.
|
|
881
1080
|
*
|
|
882
1081
|
* Sequential when the caller asks for it: a lone child gains nothing from the
|
|
@@ -1045,6 +1244,27 @@ function trackCancellation(onSignal) {
|
|
|
1045
1244
|
};
|
|
1046
1245
|
}
|
|
1047
1246
|
/**
|
|
1247
|
+
* Watch a child's stderr for V8's out-of-memory report. Reads alongside
|
|
1248
|
+
* whatever else consumes the stream, and never alters it.
|
|
1249
|
+
*
|
|
1250
|
+
* @param child - The spawned child.
|
|
1251
|
+
* @param onExhausted - Called once, when the report is seen.
|
|
1252
|
+
*/
|
|
1253
|
+
function watchOutOfMemory(child, onExhausted) {
|
|
1254
|
+
let tail = "";
|
|
1255
|
+
let seen = false;
|
|
1256
|
+
child.stderr?.on("data", (chunk) => {
|
|
1257
|
+
if (seen) return;
|
|
1258
|
+
const text = tail + String(chunk);
|
|
1259
|
+
if (OUT_OF_MEMORY.test(text)) {
|
|
1260
|
+
seen = true;
|
|
1261
|
+
onExhausted();
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
tail = text.slice(-64);
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1048
1268
|
* Start every command as one `concurrently` group and announce the children.
|
|
1049
1269
|
* Unlike the previous `killOthersOn: ["failure"]` behaviour, an ordinary lint
|
|
1050
1270
|
* failure in one child no longer kills its siblings — each runs to the end so
|
|
@@ -1075,6 +1295,7 @@ async function startGroup(commands, cwd, outputStream = process$1.stdout) {
|
|
|
1075
1295
|
}];
|
|
1076
1296
|
}));
|
|
1077
1297
|
const logger = new Logger({});
|
|
1298
|
+
const exhausted = /* @__PURE__ */ new Set();
|
|
1078
1299
|
const abortController = new AbortController();
|
|
1079
1300
|
const stopTracking = trackCancellation();
|
|
1080
1301
|
const { result } = createConcurrently(Array.from(launches, ([name, { command }]) => {
|
|
@@ -1103,7 +1324,11 @@ async function startGroup(commands, cwd, outputStream = process$1.stdout) {
|
|
|
1103
1324
|
spawn: (name, options) => {
|
|
1104
1325
|
const launch = launches.get(name);
|
|
1105
1326
|
if (launch === void 0) throw new Error(`isentinel-lint: no engine registered as "${name}".`);
|
|
1106
|
-
|
|
1327
|
+
const child = launchEngine(launch, options);
|
|
1328
|
+
if (launch.command.watchHeap) watchOutOfMemory(child, () => {
|
|
1329
|
+
exhausted.add(launch.command.label);
|
|
1330
|
+
});
|
|
1331
|
+
return child;
|
|
1107
1332
|
}
|
|
1108
1333
|
});
|
|
1109
1334
|
for (const command of commands) announce(command);
|
|
@@ -1114,6 +1339,7 @@ async function startGroup(commands, cwd, outputStream = process$1.stdout) {
|
|
|
1114
1339
|
return 1;
|
|
1115
1340
|
} finally {
|
|
1116
1341
|
stopTracking();
|
|
1342
|
+
for (const label of exhausted) process$1.stderr.write(outOfMemoryHint(label));
|
|
1117
1343
|
}
|
|
1118
1344
|
}
|
|
1119
1345
|
function signalExitCode(signal) {
|
|
@@ -1130,6 +1356,8 @@ function cancelledCode() {
|
|
|
1130
1356
|
}
|
|
1131
1357
|
async function spawnChild(command, cwd) {
|
|
1132
1358
|
const bin = resolveLocalBin(command.bin, cwd);
|
|
1359
|
+
const watched = command.watchHeap;
|
|
1360
|
+
let exhausted = false;
|
|
1133
1361
|
return new Promise((resolve) => {
|
|
1134
1362
|
const child = launchEngine({
|
|
1135
1363
|
bin,
|
|
@@ -1140,8 +1368,20 @@ async function spawnChild(command, cwd) {
|
|
|
1140
1368
|
...process$1.env,
|
|
1141
1369
|
...command.env
|
|
1142
1370
|
},
|
|
1143
|
-
stdio:
|
|
1371
|
+
stdio: [
|
|
1372
|
+
"inherit",
|
|
1373
|
+
"inherit",
|
|
1374
|
+
watched ? "pipe" : "inherit"
|
|
1375
|
+
]
|
|
1144
1376
|
});
|
|
1377
|
+
if (watched) {
|
|
1378
|
+
child.stderr?.on("data", (chunk) => {
|
|
1379
|
+
process$1.stderr.write(chunk);
|
|
1380
|
+
});
|
|
1381
|
+
watchOutOfMemory(child, () => {
|
|
1382
|
+
exhausted = true;
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1145
1385
|
announce(command);
|
|
1146
1386
|
const stopTracking = trackCancellation((signal) => {
|
|
1147
1387
|
child.kill(signal);
|
|
@@ -1152,6 +1392,7 @@ async function spawnChild(command, cwd) {
|
|
|
1152
1392
|
});
|
|
1153
1393
|
child.on("close", (code, signal) => {
|
|
1154
1394
|
stopTracking();
|
|
1395
|
+
if (exhausted) process$1.stderr.write(outOfMemoryHint(command.label));
|
|
1155
1396
|
resolve(code ?? (signal === null ? 1 : signalExitCode(signal)));
|
|
1156
1397
|
});
|
|
1157
1398
|
});
|
|
@@ -1236,7 +1477,8 @@ function composeOxlintCommand(options, context) {
|
|
|
1236
1477
|
args,
|
|
1237
1478
|
bin: "oxlint",
|
|
1238
1479
|
env: {},
|
|
1239
|
-
label: "oxc"
|
|
1480
|
+
label: "oxc",
|
|
1481
|
+
watchHeap: false
|
|
1240
1482
|
};
|
|
1241
1483
|
}
|
|
1242
1484
|
/**
|
|
@@ -1254,11 +1496,14 @@ function composeEslintCommand(options, context) {
|
|
|
1254
1496
|
if (options.agents) args.push("--format", context.agentsFormatterPath);
|
|
1255
1497
|
if (context.fix) args.push("--fix");
|
|
1256
1498
|
args.push(...options.eslintArgs, ...pathArguments(context.paths));
|
|
1499
|
+
const environment = { ESLINT_TYPE_AWARE: context.typeAwareEnv };
|
|
1500
|
+
if (context.heap?.nodeOptions !== void 0) environment["NODE_OPTIONS"] = context.heap.nodeOptions;
|
|
1257
1501
|
return {
|
|
1258
1502
|
args,
|
|
1259
1503
|
bin: "eslint",
|
|
1260
|
-
env:
|
|
1261
|
-
label: context.eslintLabel
|
|
1504
|
+
env: environment,
|
|
1505
|
+
label: context.eslintLabel,
|
|
1506
|
+
watchHeap: context.heap?.watch ?? false
|
|
1262
1507
|
};
|
|
1263
1508
|
}
|
|
1264
1509
|
/**
|
|
@@ -1306,6 +1551,7 @@ function composePasses(passes, runPlan, options) {
|
|
|
1306
1551
|
concurrency: pass.concurrency,
|
|
1307
1552
|
eslintLabel: pass.descriptor.label,
|
|
1308
1553
|
fix: false,
|
|
1554
|
+
heap: pass.heap,
|
|
1309
1555
|
paths: options.paths,
|
|
1310
1556
|
typeAwareEnv: pass.descriptor.typeAwareEnv
|
|
1311
1557
|
}));
|
|
@@ -4851,6 +5097,7 @@ function resolveWorkerLimits(environment, availableParallelism, ci) {
|
|
|
4851
5097
|
const explicit = parsePositiveInteger(environment["LINT_MAX_WORKERS"]);
|
|
4852
5098
|
const maxWorkers = explicit ?? (ci ? availableParallelism : Math.floor(availableParallelism / 4));
|
|
4853
5099
|
return {
|
|
5100
|
+
explicitMaxWorkers: explicit !== void 0,
|
|
4854
5101
|
filesPerWorker,
|
|
4855
5102
|
maxWorkers,
|
|
4856
5103
|
typedMaxWorkers: explicit ?? Math.min(maxWorkers, 6)
|
|
@@ -4943,6 +5190,17 @@ function selectPasses(options, ci) {
|
|
|
4943
5190
|
return [FAST_PASS, TYPED_PASS];
|
|
4944
5191
|
}
|
|
4945
5192
|
/**
|
|
5193
|
+
* Whether a pass builds a TypeScript program in each of its workers. The pass
|
|
5194
|
+
* that runs no builder is exactly the one that builds no program, so
|
|
5195
|
+
* `invalidation` records both.
|
|
5196
|
+
*
|
|
5197
|
+
* @param descriptor - The pass.
|
|
5198
|
+
* @returns Whether its workers hold a program, and so need heap sizing.
|
|
5199
|
+
*/
|
|
5200
|
+
function buildsProgram(descriptor) {
|
|
5201
|
+
return descriptor.invalidation !== "none";
|
|
5202
|
+
}
|
|
5203
|
+
/**
|
|
4946
5204
|
* The worker cap for a pass. `invalidation` already records whether a pass
|
|
4947
5205
|
* builds a TypeScript program — the fast pass runs no builder precisely because
|
|
4948
5206
|
* it builds none — so it doubles as the cap selector rather than restating the
|
|
@@ -4953,7 +5211,7 @@ function selectPasses(options, ci) {
|
|
|
4953
5211
|
* @returns The worker cap for this pass.
|
|
4954
5212
|
*/
|
|
4955
5213
|
function maxWorkersFor(descriptor, limits) {
|
|
4956
|
-
return descriptor
|
|
5214
|
+
return buildsProgram(descriptor) ? limits.typedMaxWorkers : limits.maxWorkers;
|
|
4957
5215
|
}
|
|
4958
5216
|
//#endregion
|
|
4959
5217
|
//#region src/lint-cli/lib/plan/fix.ts
|
|
@@ -5018,13 +5276,18 @@ function collectFixTargets(passes, run, files) {
|
|
|
5018
5276
|
* @returns The fix child, or `undefined` when nothing was reported.
|
|
5019
5277
|
*/
|
|
5020
5278
|
function planFixChild(passes, run, inputs) {
|
|
5021
|
-
const { files, limits, options } = inputs;
|
|
5279
|
+
const { files, heap, limits, options } = inputs;
|
|
5022
5280
|
const covered = options.cache ? collectFixTargets(passes, run, files) : [];
|
|
5023
5281
|
const uncovered = options.cache ? files.outsideCwdTargets : options.paths;
|
|
5024
5282
|
const targets = [...covered, ...uncovered];
|
|
5025
5283
|
if (targets.length === 0) return;
|
|
5026
5284
|
const cacheFile = cacheFileFor(CACHE_FILE_DEFAULT, run.key);
|
|
5027
5285
|
if (covered.length > 0) openCache(path.resolve(run.cwd, cacheFile), run.ci)?.removeEntries(covered);
|
|
5286
|
+
const concurrency = options.concurrency ?? computeWorkerCount({
|
|
5287
|
+
dirtyCount: targets.length,
|
|
5288
|
+
filesPerWorker: limits.filesPerWorker,
|
|
5289
|
+
maxWorkers: capWorkersForHeap(limits.typedMaxWorkers, limits.explicitMaxWorkers, heap)
|
|
5290
|
+
});
|
|
5028
5291
|
return composeEslintCommand({
|
|
5029
5292
|
...options,
|
|
5030
5293
|
cache: options.cache && uncovered.length === 0
|
|
@@ -5032,13 +5295,13 @@ function planFixChild(passes, run, inputs) {
|
|
|
5032
5295
|
agentsFormatterPath: inputs.agentsFormatterPath,
|
|
5033
5296
|
cacheLocation: cacheFile,
|
|
5034
5297
|
ci: run.ci,
|
|
5035
|
-
concurrency
|
|
5036
|
-
dirtyCount: targets.length,
|
|
5037
|
-
filesPerWorker: limits.filesPerWorker,
|
|
5038
|
-
maxWorkers: limits.typedMaxWorkers
|
|
5039
|
-
}),
|
|
5298
|
+
concurrency,
|
|
5040
5299
|
eslintLabel: FULL_PASS.label,
|
|
5041
5300
|
fix: true,
|
|
5301
|
+
heap: planPassHeap(FULL_PASS.label, heap, {
|
|
5302
|
+
concurrency,
|
|
5303
|
+
dirtyCount: targets.length
|
|
5304
|
+
}),
|
|
5042
5305
|
paths: targets,
|
|
5043
5306
|
typeAwareEnv: FULL_PASS.typeAwareEnv
|
|
5044
5307
|
});
|
|
@@ -5818,12 +6081,12 @@ function sizePasses(descriptors, run, inputs) {
|
|
|
5818
6081
|
* @returns The number of dirty files.
|
|
5819
6082
|
*/
|
|
5820
6083
|
function mutatingDirtyCount(descriptor, cacheLocation, targetFiles, { clearedCaches, run }) {
|
|
5821
|
-
const
|
|
6084
|
+
const program = buildsProgram(descriptor);
|
|
5822
6085
|
const mode = descriptor.invalidation === "only" ? "only" : void 0;
|
|
5823
|
-
if (clearedCaches.has(cacheLocation) && (!
|
|
6086
|
+
if (clearedCaches.has(cacheLocation) && (!program || hasBuilderState(run, mode))) return targetFiles.length;
|
|
5824
6087
|
const cache = openCache(cacheLocation, run.ci);
|
|
5825
6088
|
const dirty = new Set((cache?.getUpdatedFiles(targetFiles) ?? targetFiles).map((file) => normalizePath(file)));
|
|
5826
|
-
if (
|
|
6089
|
+
if (program) {
|
|
5827
6090
|
const outcome = applyTypeAwareInvalidation(run, {
|
|
5828
6091
|
alreadyDirty: dirty,
|
|
5829
6092
|
cache,
|
|
@@ -5880,17 +6143,24 @@ function sizePass(descriptor, context) {
|
|
|
5880
6143
|
const dirtyCount = passDirtyCount(descriptor, cacheFile, context);
|
|
5881
6144
|
const conservative = context.files.outsideCwdTargets.length > 0;
|
|
5882
6145
|
const filesPerWorker = descriptor.filesPerWorker(context.limits, context.run.environment);
|
|
5883
|
-
const
|
|
6146
|
+
const program = buildsProgram(descriptor);
|
|
6147
|
+
const passMaxWorkers = maxWorkersFor(descriptor, context.limits);
|
|
6148
|
+
const maxWorkers = program ? capWorkersForHeap(passMaxWorkers, context.limits.explicitMaxWorkers, context.heap) : passMaxWorkers;
|
|
5884
6149
|
const sizingDirtyCount = conservative ? maxWorkers * filesPerWorker : dirtyCount;
|
|
5885
6150
|
const concurrency = context.options.concurrency ?? computeWorkerCount({
|
|
5886
6151
|
dirtyCount: sizingDirtyCount,
|
|
5887
6152
|
filesPerWorker,
|
|
5888
6153
|
maxWorkers
|
|
5889
6154
|
});
|
|
6155
|
+
const heap = program ? planPassHeap(descriptor.label, context.heap, {
|
|
6156
|
+
concurrency,
|
|
6157
|
+
dirtyCount: sizingDirtyCount
|
|
6158
|
+
}) : void 0;
|
|
5890
6159
|
if (context.run.mutate && context.multiPass && descriptor === TYPED_PASS && !conservative && dirtyCount === 0) return {
|
|
5891
6160
|
cacheFile,
|
|
5892
6161
|
concurrency,
|
|
5893
6162
|
descriptor,
|
|
6163
|
+
heap,
|
|
5894
6164
|
shouldRun: false,
|
|
5895
6165
|
skipReason: TYPED_SKIP_NOTICE
|
|
5896
6166
|
};
|
|
@@ -5898,6 +6168,7 @@ function sizePass(descriptor, context) {
|
|
|
5898
6168
|
cacheFile,
|
|
5899
6169
|
concurrency,
|
|
5900
6170
|
descriptor,
|
|
6171
|
+
heap,
|
|
5901
6172
|
shouldRun: true,
|
|
5902
6173
|
skipReason: void 0
|
|
5903
6174
|
};
|
|
@@ -5918,9 +6189,10 @@ function sizePass(descriptor, context) {
|
|
|
5918
6189
|
*
|
|
5919
6190
|
* @param options - The parsed CLI options.
|
|
5920
6191
|
* @param run - The run context (cwd, variant key, environment, mutate).
|
|
6192
|
+
* @param memory - The machine's memory facts (injected in tests).
|
|
5921
6193
|
* @returns The staged run plan.
|
|
5922
6194
|
*/
|
|
5923
|
-
function plan(options, run) {
|
|
6195
|
+
function plan(options, run, memory = probeMemory()) {
|
|
5924
6196
|
const { ci, cwd, environment, mutate } = run;
|
|
5925
6197
|
const runEslint = !options.oxlint;
|
|
5926
6198
|
const oxlintTypeAware = resolveOxlintTypeAware(options);
|
|
@@ -5945,6 +6217,7 @@ function plan(options, run) {
|
|
|
5945
6217
|
const files = collectRepoFiles(cwd, options.paths);
|
|
5946
6218
|
const newestBustMtime = maxMtimeMs(files.bustFiles);
|
|
5947
6219
|
const limits = resolveWorkerLimits(environment, availableParallelism(), ci);
|
|
6220
|
+
const heap = resolveHeapBudget(environment, memory);
|
|
5948
6221
|
const oxlintDecision = resolveOxlintRun(run, {
|
|
5949
6222
|
files,
|
|
5950
6223
|
runEslint,
|
|
@@ -5964,6 +6237,7 @@ function plan(options, run) {
|
|
|
5964
6237
|
const inputs = {
|
|
5965
6238
|
clearedCaches,
|
|
5966
6239
|
files: sizingFiles,
|
|
6240
|
+
heap,
|
|
5967
6241
|
limits,
|
|
5968
6242
|
multiPass: descriptors.length > 1,
|
|
5969
6243
|
newestBustMtime,
|
|
@@ -5991,6 +6265,7 @@ function plan(options, run) {
|
|
|
5991
6265
|
return planFixChild(passes, run, {
|
|
5992
6266
|
agentsFormatterPath,
|
|
5993
6267
|
files: sizingFiles,
|
|
6268
|
+
heap,
|
|
5994
6269
|
limits,
|
|
5995
6270
|
options
|
|
5996
6271
|
});
|
|
@@ -6059,6 +6334,7 @@ async function runLint(argv, cwd = process$1.cwd(), environment = process$1.env,
|
|
|
6059
6334
|
const { commands, notice } = compose(staged.eager, options);
|
|
6060
6335
|
if (options.print) {
|
|
6061
6336
|
for (const command of commands) process$1.stdout.write(`${formatCommandLine(command)}\n`);
|
|
6337
|
+
for (const pass of staged.eager.passes) if (pass.shouldRun && pass.heap !== void 0) process$1.stderr.write(pass.heap.note);
|
|
6062
6338
|
return 0;
|
|
6063
6339
|
}
|
|
6064
6340
|
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.");
|
package/dist/oxlint.d.mts
CHANGED
|
@@ -1382,7 +1382,10 @@ interface OxlintMainRuleDefaults {
|
|
|
1382
1382
|
"*": "off";
|
|
1383
1383
|
};
|
|
1384
1384
|
"prefer-const": {
|
|
1385
|
-
"*": "error"
|
|
1385
|
+
"*": ["error", {
|
|
1386
|
+
"destructuring": "all";
|
|
1387
|
+
"ignoreReadBeforeAssign": true;
|
|
1388
|
+
}];
|
|
1386
1389
|
};
|
|
1387
1390
|
"prefer-destructuring": {
|
|
1388
1391
|
"*": "off";
|
|
@@ -2080,7 +2083,9 @@ interface OxlintMainRuleDefaults {
|
|
|
2080
2083
|
"*": "off";
|
|
2081
2084
|
};
|
|
2082
2085
|
"typescript/no-empty-object-type": {
|
|
2083
|
-
"*": "error"
|
|
2086
|
+
"*": ["error", {
|
|
2087
|
+
"allowInterfaces": "always";
|
|
2088
|
+
}];
|
|
2084
2089
|
};
|
|
2085
2090
|
"typescript/no-explicit-any": {
|
|
2086
2091
|
"*": "off";
|
package/dist/oxlint.mjs
CHANGED
|
@@ -8479,11 +8479,15 @@ function sonarjsTestRules({ jest = false, roblox = true } = {}) {
|
|
|
8479
8479
|
}
|
|
8480
8480
|
//#endregion
|
|
8481
8481
|
//#region src/oxlint/configs/sonarjs.ts
|
|
8482
|
-
function oxlintSonarjs(
|
|
8482
|
+
function oxlintSonarjs({ excludeFiles, isInEditor, roblox }) {
|
|
8483
8483
|
return createOxlintConfigs({
|
|
8484
|
-
name: "isentinel/sonarjs",
|
|
8484
|
+
name: excludeFiles ? "isentinel/sonarjs/complement" : "isentinel/sonarjs",
|
|
8485
|
+
...excludeFiles ? { excludeFiles } : {},
|
|
8485
8486
|
files: [GLOB_SRC],
|
|
8486
|
-
rules: sonarjsRules(
|
|
8487
|
+
rules: sonarjsRules({
|
|
8488
|
+
isInEditor,
|
|
8489
|
+
roblox
|
|
8490
|
+
})
|
|
8487
8491
|
});
|
|
8488
8492
|
}
|
|
8489
8493
|
//#endregion
|
|
@@ -9006,7 +9010,6 @@ function typescriptTypeAwareRules({ roblox = true } = {}) {
|
|
|
9006
9010
|
"ts/no-confusing-void-expression": "error",
|
|
9007
9011
|
"ts/no-deprecated": "error",
|
|
9008
9012
|
"ts/no-duplicate-type-constituents": "error",
|
|
9009
|
-
"ts/no-empty-object-type": "error",
|
|
9010
9013
|
"ts/no-floating-promises": ["error", {
|
|
9011
9014
|
checkThenables: roblox,
|
|
9012
9015
|
ignoreVoid: true
|
|
@@ -9107,7 +9110,6 @@ function typescriptRecommendedOverrides() {
|
|
|
9107
9110
|
"no-unsafe-negation": "off",
|
|
9108
9111
|
"no-var": "error",
|
|
9109
9112
|
"no-with": "off",
|
|
9110
|
-
"prefer-const": "error",
|
|
9111
9113
|
"prefer-rest-params": "error",
|
|
9112
9114
|
"prefer-spread": "error"
|
|
9113
9115
|
};
|
|
@@ -9488,7 +9490,21 @@ function isentinel(factoryOptions, ...userConfigs) {
|
|
|
9488
9490
|
componentExts: componentExtensions,
|
|
9489
9491
|
stylistic: stylisticOptions
|
|
9490
9492
|
}));
|
|
9491
|
-
if (needsComplementOverlay) configs.push(
|
|
9493
|
+
if (needsComplementOverlay) configs.push(oxlintJavascript({
|
|
9494
|
+
...getOverrides(options, "javascript"),
|
|
9495
|
+
excludeFiles: robloxScopedFiles,
|
|
9496
|
+
isInEditor,
|
|
9497
|
+
roblox: false,
|
|
9498
|
+
stylistic: stylisticOptions
|
|
9499
|
+
}), oxlintImports({
|
|
9500
|
+
excludeFiles: robloxScopedFiles,
|
|
9501
|
+
roblox: false,
|
|
9502
|
+
stylistic: stylisticOptions
|
|
9503
|
+
}), oxlintSonarjs({
|
|
9504
|
+
excludeFiles: robloxScopedFiles,
|
|
9505
|
+
isInEditor,
|
|
9506
|
+
roblox: false
|
|
9507
|
+
}), oxlintTypescript({
|
|
9492
9508
|
...resolveSubOptions(options, "typescript"),
|
|
9493
9509
|
...getOverrides(options, "typescript"),
|
|
9494
9510
|
componentExts: componentExtensions,
|
|
@@ -9496,21 +9512,11 @@ function isentinel(factoryOptions, ...userConfigs) {
|
|
|
9496
9512
|
roblox: false,
|
|
9497
9513
|
stylistic: stylisticOptions,
|
|
9498
9514
|
typeAware
|
|
9499
|
-
}), oxlintJavascript({
|
|
9500
|
-
...getOverrides(options, "javascript"),
|
|
9501
|
-
excludeFiles: robloxScopedFiles,
|
|
9502
|
-
isInEditor,
|
|
9503
|
-
roblox: false,
|
|
9504
|
-
stylistic: stylisticOptions
|
|
9505
9515
|
}), oxlintUnicorn({
|
|
9506
9516
|
...resolveSubOptions(options, "unicorn"),
|
|
9507
9517
|
excludeFiles: robloxScopedFiles,
|
|
9508
9518
|
roblox: false,
|
|
9509
9519
|
stylistic: stylisticOptions
|
|
9510
|
-
}), oxlintImports({
|
|
9511
|
-
excludeFiles: robloxScopedFiles,
|
|
9512
|
-
roblox: false,
|
|
9513
|
-
stylistic: stylisticOptions
|
|
9514
9520
|
}));
|
|
9515
9521
|
if (enableE18e !== false && hasComplement) configs.push(oxlintE18e({
|
|
9516
9522
|
excludeFiles: robloxScopedFiles,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isentinel/eslint-config",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "iSentinel's ESLint config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint-config",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@typescript-eslint/eslint-plugin": "8.65.0",
|
|
68
68
|
"@typescript-eslint/parser": "8.65.0",
|
|
69
69
|
"ansis": "4.3.1",
|
|
70
|
-
"concurrently": "10.0.
|
|
70
|
+
"concurrently": "10.0.6",
|
|
71
71
|
"eslint-config-flat-gitignore": "2.3.0",
|
|
72
72
|
"eslint-config-prettier": "10.1.8",
|
|
73
73
|
"eslint-flat-config-utils": "3.2.0",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"globals": "17.7.0",
|
|
99
99
|
"jsonc-eslint-parser": "3.1.0",
|
|
100
100
|
"local-pkg": "1.2.1",
|
|
101
|
-
"oxfmt": "0.
|
|
101
|
+
"oxfmt": "0.72.0",
|
|
102
102
|
"oxlint-plugin-eslint": "1.78.0",
|
|
103
103
|
"oxlint-plugin-oxlint-comments": "0.1.0",
|
|
104
104
|
"prettier": "3.9.6",
|
|
@@ -145,7 +145,7 @@
|
|
|
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
|
|
148
|
+
"@isentinel/eslint-config": "6.1.0"
|
|
149
149
|
},
|
|
150
150
|
"peerDependencies": {
|
|
151
151
|
"@vitest/eslint-plugin": "^1.6.4",
|