@eslint-config-snapshot/cli 0.4.0 → 0.6.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/CHANGELOG.md +22 -0
- package/dist/index.cjs +283 -52
- package/dist/index.js +284 -52
- package/package.json +2 -2
- package/src/index.ts +334 -55
- package/test/cli.integration.test.ts +8 -0
- package/test/cli.npm-isolated.integration.test.ts +27 -6
- package/test/cli.pnpm-isolated.integration.test.ts +27 -10
- package/test/cli.terminal.integration.test.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -14,44 +14,59 @@ import {
|
|
|
14
14
|
loadConfig,
|
|
15
15
|
normalizePath,
|
|
16
16
|
readSnapshotFile,
|
|
17
|
+
resolveEslintVersionForWorkspace,
|
|
17
18
|
sampleWorkspaceFiles,
|
|
18
19
|
writeSnapshotFile
|
|
19
20
|
} from "@eslint-config-snapshot/api";
|
|
20
21
|
import { Command, CommanderError, InvalidArgumentError } from "commander";
|
|
21
22
|
import fg from "fast-glob";
|
|
23
|
+
import { existsSync, readFileSync } from "fs";
|
|
22
24
|
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
23
25
|
import path from "path";
|
|
24
26
|
import { createInterface } from "readline";
|
|
25
27
|
var SNAPSHOT_DIR = ".eslint-config-snapshot";
|
|
26
28
|
var UPDATE_HINT = "Tip: when you intentionally accept changes, run `eslint-config-snapshot --update` to refresh the baseline.\n";
|
|
29
|
+
var activeRunTimer;
|
|
30
|
+
var cachedCliVersion;
|
|
27
31
|
async function runCli(command, cwd, flags = []) {
|
|
28
32
|
const argv = command ? [command, ...flags] : [...flags];
|
|
29
33
|
return runArgv(argv, cwd);
|
|
30
34
|
}
|
|
31
35
|
async function runArgv(argv, cwd) {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
let actionCode;
|
|
37
|
-
const program = createProgram(cwd, (code) => {
|
|
38
|
-
actionCode = code;
|
|
39
|
-
});
|
|
36
|
+
const invocationLabel = resolveInvocationLabel(argv);
|
|
37
|
+
beginRunTimer(invocationLabel);
|
|
38
|
+
let exitCode = 1;
|
|
40
39
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return 0;
|
|
46
|
-
}
|
|
47
|
-
return error.exitCode;
|
|
40
|
+
const hasCommandToken = argv.some((token) => !token.startsWith("-"));
|
|
41
|
+
if (!hasCommandToken) {
|
|
42
|
+
exitCode = await runDefaultInvocation(argv, cwd);
|
|
43
|
+
return exitCode;
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
let actionCode;
|
|
46
|
+
const program = createProgram(cwd, (code) => {
|
|
47
|
+
actionCode = code;
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
await program.parseAsync(argv, { from: "user" });
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error instanceof CommanderError) {
|
|
53
|
+
if (error.code === "commander.helpDisplayed") {
|
|
54
|
+
exitCode = 0;
|
|
55
|
+
return exitCode;
|
|
56
|
+
}
|
|
57
|
+
exitCode = error.exitCode;
|
|
58
|
+
return exitCode;
|
|
59
|
+
}
|
|
60
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
61
|
+
process.stderr.write(`${message}
|
|
51
62
|
`);
|
|
52
|
-
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
exitCode = actionCode ?? 0;
|
|
66
|
+
return exitCode;
|
|
67
|
+
} finally {
|
|
68
|
+
endRunTimer(exitCode);
|
|
53
69
|
}
|
|
54
|
-
return actionCode ?? 0;
|
|
55
70
|
}
|
|
56
71
|
async function runDefaultInvocation(argv, cwd) {
|
|
57
72
|
const known = /* @__PURE__ */ new Set(["-u", "--update", "-h", "--help"]);
|
|
@@ -157,6 +172,13 @@ function parseInitPreset(value) {
|
|
|
157
172
|
}
|
|
158
173
|
async function executeCheck(cwd, format, defaultInvocation = false) {
|
|
159
174
|
const foundConfig = await findConfigPath(cwd);
|
|
175
|
+
const storedSnapshots = await loadStoredSnapshots(cwd);
|
|
176
|
+
if (format !== "status") {
|
|
177
|
+
writeRunContextHeader(cwd, defaultInvocation ? "check" : `check:${format}`, foundConfig?.path, storedSnapshots);
|
|
178
|
+
if (shouldShowRunLogs()) {
|
|
179
|
+
writeSubtleInfo("\u{1F50E} Checking current ESLint configuration...\n");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
160
182
|
if (!foundConfig) {
|
|
161
183
|
writeSubtleInfo(
|
|
162
184
|
"Tip: no explicit config found. Using safe built-in defaults. Run `eslint-config-snapshot init` to customize when needed.\n"
|
|
@@ -174,7 +196,6 @@ async function executeCheck(cwd, format, defaultInvocation = false) {
|
|
|
174
196
|
}
|
|
175
197
|
throw error;
|
|
176
198
|
}
|
|
177
|
-
const storedSnapshots = await loadStoredSnapshots(cwd);
|
|
178
199
|
if (storedSnapshots.size === 0) {
|
|
179
200
|
const summary = summarizeSnapshots(currentSnapshots);
|
|
180
201
|
process.stdout.write(
|
|
@@ -201,6 +222,7 @@ async function executeCheck(cwd, format, defaultInvocation = false) {
|
|
|
201
222
|
return 1;
|
|
202
223
|
}
|
|
203
224
|
const changes = compareSnapshotMaps(storedSnapshots, currentSnapshots);
|
|
225
|
+
const eslintVersionsByGroup = shouldShowRunLogs() ? await resolveGroupEslintVersions(cwd) : /* @__PURE__ */ new Map();
|
|
204
226
|
if (format === "status") {
|
|
205
227
|
if (changes.length === 0) {
|
|
206
228
|
process.stdout.write("clean\n");
|
|
@@ -213,6 +235,7 @@ async function executeCheck(cwd, format, defaultInvocation = false) {
|
|
|
213
235
|
if (format === "diff") {
|
|
214
236
|
if (changes.length === 0) {
|
|
215
237
|
process.stdout.write("Great news: no snapshot changes detected.\n");
|
|
238
|
+
writeEslintVersionSummary(eslintVersionsByGroup);
|
|
216
239
|
return 0;
|
|
217
240
|
}
|
|
218
241
|
for (const change of changes) {
|
|
@@ -222,10 +245,15 @@ async function executeCheck(cwd, format, defaultInvocation = false) {
|
|
|
222
245
|
writeSubtleInfo(UPDATE_HINT);
|
|
223
246
|
return 1;
|
|
224
247
|
}
|
|
225
|
-
return printWhatChanged(changes, currentSnapshots);
|
|
248
|
+
return printWhatChanged(changes, currentSnapshots, eslintVersionsByGroup);
|
|
226
249
|
}
|
|
227
250
|
async function executeUpdate(cwd, printSummary) {
|
|
228
251
|
const foundConfig = await findConfigPath(cwd);
|
|
252
|
+
const storedSnapshots = await loadStoredSnapshots(cwd);
|
|
253
|
+
writeRunContextHeader(cwd, "update", foundConfig?.path, storedSnapshots);
|
|
254
|
+
if (shouldShowRunLogs()) {
|
|
255
|
+
writeSubtleInfo("\u{1F50E} Checking current ESLint configuration...\n");
|
|
256
|
+
}
|
|
229
257
|
if (!foundConfig) {
|
|
230
258
|
writeSubtleInfo(
|
|
231
259
|
"Tip: no explicit config found. Using safe built-in defaults. Run `eslint-config-snapshot init` to customize when needed.\n"
|
|
@@ -247,16 +275,24 @@ async function executeUpdate(cwd, printSummary) {
|
|
|
247
275
|
if (printSummary) {
|
|
248
276
|
const summary = summarizeSnapshots(currentSnapshots);
|
|
249
277
|
const color = createColorizer();
|
|
278
|
+
const eslintVersionsByGroup = shouldShowRunLogs() ? await resolveGroupEslintVersions(cwd) : /* @__PURE__ */ new Map();
|
|
250
279
|
writeSectionTitle("Summary", color);
|
|
251
280
|
process.stdout.write(
|
|
252
281
|
`Baseline updated: ${summary.groups} groups, ${summary.rules} rules.
|
|
253
282
|
Severity mix: ${summary.error} errors, ${summary.warn} warnings, ${summary.off} off.
|
|
254
283
|
`
|
|
255
284
|
);
|
|
285
|
+
writeEslintVersionSummary(eslintVersionsByGroup);
|
|
256
286
|
}
|
|
257
287
|
return 0;
|
|
258
288
|
}
|
|
259
289
|
async function executePrint(cwd, format) {
|
|
290
|
+
const foundConfig = await findConfigPath(cwd);
|
|
291
|
+
const storedSnapshots = await loadStoredSnapshots(cwd);
|
|
292
|
+
writeRunContextHeader(cwd, `print:${format}`, foundConfig?.path, storedSnapshots);
|
|
293
|
+
if (shouldShowRunLogs()) {
|
|
294
|
+
writeSubtleInfo("\u{1F50E} Checking current ESLint configuration...\n");
|
|
295
|
+
}
|
|
260
296
|
const currentSnapshots = await computeCurrentSnapshots(cwd);
|
|
261
297
|
if (format === "short") {
|
|
262
298
|
process.stdout.write(formatShortPrint([...currentSnapshots.values()]));
|
|
@@ -271,6 +307,11 @@ async function executePrint(cwd, format) {
|
|
|
271
307
|
}
|
|
272
308
|
async function executeConfig(cwd, format) {
|
|
273
309
|
const foundConfig = await findConfigPath(cwd);
|
|
310
|
+
const storedSnapshots = await loadStoredSnapshots(cwd);
|
|
311
|
+
writeRunContextHeader(cwd, `config:${format}`, foundConfig?.path, storedSnapshots);
|
|
312
|
+
if (shouldShowRunLogs()) {
|
|
313
|
+
writeSubtleInfo("\u{1F50E} Resolving effective runtime configuration...\n");
|
|
314
|
+
}
|
|
274
315
|
const config = await loadConfig(cwd);
|
|
275
316
|
const resolved = await resolveWorkspaceAssignments(cwd, config);
|
|
276
317
|
const payload = {
|
|
@@ -456,8 +497,8 @@ ${JSON.stringify(configObject, null, 2)}
|
|
|
456
497
|
}
|
|
457
498
|
async function askInitPreferences() {
|
|
458
499
|
const { select } = await import("@inquirer/prompts");
|
|
459
|
-
const target = await askInitTarget(select);
|
|
460
|
-
const preset = await askInitPreset(select);
|
|
500
|
+
const target = await runPromptWithPausedTimer(() => askInitTarget(select));
|
|
501
|
+
const preset = await runPromptWithPausedTimer(() => askInitPreset(select));
|
|
461
502
|
return { target, preset };
|
|
462
503
|
}
|
|
463
504
|
async function askInitTarget(selectPrompt) {
|
|
@@ -480,8 +521,10 @@ async function askInitPreset(selectPrompt) {
|
|
|
480
521
|
});
|
|
481
522
|
}
|
|
482
523
|
function askQuestion(rl, prompt) {
|
|
524
|
+
pauseRunTimer();
|
|
483
525
|
return new Promise((resolve) => {
|
|
484
526
|
rl.question(prompt, (answer) => {
|
|
527
|
+
resumeRunTimer();
|
|
485
528
|
resolve(answer);
|
|
486
529
|
});
|
|
487
530
|
});
|
|
@@ -627,11 +670,13 @@ async function askRecommendedGroupAssignments(workspaces) {
|
|
|
627
670
|
'Recommended setup: default group "*" is a dynamic catch-all for every discovered workspace.\n'
|
|
628
671
|
);
|
|
629
672
|
process.stdout.write("Select only workspaces that should move to explicit static groups.\n");
|
|
630
|
-
const overrides = await
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
673
|
+
const overrides = await runPromptWithPausedTimer(
|
|
674
|
+
() => checkbox({
|
|
675
|
+
message: 'Choose exception workspaces (leave empty to keep all in default "*"):',
|
|
676
|
+
choices: workspaces.map((workspace) => ({ name: workspace, value: workspace })),
|
|
677
|
+
pageSize: Math.min(12, Math.max(4, workspaces.length))
|
|
678
|
+
})
|
|
679
|
+
);
|
|
635
680
|
const assignments = /* @__PURE__ */ new Map();
|
|
636
681
|
let nextGroup = 1;
|
|
637
682
|
for (const workspace of overrides) {
|
|
@@ -639,13 +684,15 @@ async function askRecommendedGroupAssignments(workspaces) {
|
|
|
639
684
|
while (usedGroups.includes(nextGroup)) {
|
|
640
685
|
nextGroup += 1;
|
|
641
686
|
}
|
|
642
|
-
const selected = await
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
687
|
+
const selected = await runPromptWithPausedTimer(
|
|
688
|
+
() => select({
|
|
689
|
+
message: `Select group for ${workspace}`,
|
|
690
|
+
choices: [
|
|
691
|
+
...usedGroups.map((group) => ({ name: `group-${group}`, value: group })),
|
|
692
|
+
{ name: `create new group (group-${nextGroup})`, value: "new" }
|
|
693
|
+
]
|
|
694
|
+
})
|
|
695
|
+
);
|
|
649
696
|
const groupNumber = selected === "new" ? nextGroup : selected;
|
|
650
697
|
assignments.set(workspace, groupNumber);
|
|
651
698
|
}
|
|
@@ -688,7 +735,7 @@ function isDirectCliExecution() {
|
|
|
688
735
|
if (isDirectCliExecution()) {
|
|
689
736
|
void main();
|
|
690
737
|
}
|
|
691
|
-
function printWhatChanged(changes, currentSnapshots) {
|
|
738
|
+
function printWhatChanged(changes, currentSnapshots, eslintVersionsByGroup) {
|
|
692
739
|
const color = createColorizer();
|
|
693
740
|
const currentSummary = summarizeSnapshots(currentSnapshots);
|
|
694
741
|
const changeSummary = summarizeChanges(changes);
|
|
@@ -700,6 +747,7 @@ function printWhatChanged(changes, currentSnapshots) {
|
|
|
700
747
|
- severity mix: ${currentSummary.error} errors, ${currentSummary.warn} warnings, ${currentSummary.off} off
|
|
701
748
|
`
|
|
702
749
|
);
|
|
750
|
+
writeEslintVersionSummary(eslintVersionsByGroup);
|
|
703
751
|
return 0;
|
|
704
752
|
}
|
|
705
753
|
process.stdout.write(color.red("Heads up: snapshot drift detected.\n"));
|
|
@@ -716,6 +764,8 @@ function printWhatChanged(changes, currentSnapshots) {
|
|
|
716
764
|
|
|
717
765
|
`
|
|
718
766
|
);
|
|
767
|
+
writeEslintVersionSummary(eslintVersionsByGroup);
|
|
768
|
+
process.stdout.write("\n");
|
|
719
769
|
writeSectionTitle("Changes", color);
|
|
720
770
|
for (const change of changes) {
|
|
721
771
|
process.stdout.write(color.bold(`group ${change.groupId}
|
|
@@ -751,22 +801,7 @@ function summarizeChanges(changes) {
|
|
|
751
801
|
return { introduced, removed, severity, options, workspace };
|
|
752
802
|
}
|
|
753
803
|
function summarizeSnapshots(snapshots) {
|
|
754
|
-
|
|
755
|
-
let error = 0;
|
|
756
|
-
let warn = 0;
|
|
757
|
-
let off = 0;
|
|
758
|
-
for (const snapshot of snapshots.values()) {
|
|
759
|
-
for (const entry of Object.values(snapshot.rules)) {
|
|
760
|
-
rules += 1;
|
|
761
|
-
if (entry[0] === "error") {
|
|
762
|
-
error += 1;
|
|
763
|
-
} else if (entry[0] === "warn") {
|
|
764
|
-
warn += 1;
|
|
765
|
-
} else {
|
|
766
|
-
off += 1;
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
804
|
+
const { rules, error, warn, off } = countRuleSeverities([...snapshots.values()].map((snapshot) => snapshot.rules));
|
|
770
805
|
return { groups: snapshots.size, rules, error, warn, off };
|
|
771
806
|
}
|
|
772
807
|
function decorateDiffLine(line, color) {
|
|
@@ -796,6 +831,203 @@ function writeSubtleInfo(text) {
|
|
|
796
831
|
const color = createColorizer();
|
|
797
832
|
process.stdout.write(color.dim(text));
|
|
798
833
|
}
|
|
834
|
+
function resolveInvocationLabel(argv) {
|
|
835
|
+
const commandToken = argv.find((entry) => !entry.startsWith("-"));
|
|
836
|
+
if (commandToken) {
|
|
837
|
+
return commandToken;
|
|
838
|
+
}
|
|
839
|
+
if (argv.includes("-u") || argv.includes("--update")) {
|
|
840
|
+
return "update";
|
|
841
|
+
}
|
|
842
|
+
if (argv.includes("-h") || argv.includes("--help")) {
|
|
843
|
+
return "help";
|
|
844
|
+
}
|
|
845
|
+
return "check";
|
|
846
|
+
}
|
|
847
|
+
function shouldShowRunLogs() {
|
|
848
|
+
if (process.env.ESLINT_CONFIG_SNAPSHOT_NO_PROGRESS === "1") {
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
return process.stdout.isTTY === true;
|
|
852
|
+
}
|
|
853
|
+
function beginRunTimer(label) {
|
|
854
|
+
if (!shouldShowRunLogs()) {
|
|
855
|
+
activeRunTimer = void 0;
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
activeRunTimer = {
|
|
859
|
+
label,
|
|
860
|
+
startedAtMs: Date.now(),
|
|
861
|
+
pausedMs: 0,
|
|
862
|
+
pauseStartedAtMs: void 0
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
function endRunTimer(exitCode) {
|
|
866
|
+
if (!activeRunTimer || !shouldShowRunLogs()) {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
if (activeRunTimer.pauseStartedAtMs !== void 0) {
|
|
870
|
+
activeRunTimer.pausedMs += Date.now() - activeRunTimer.pauseStartedAtMs;
|
|
871
|
+
activeRunTimer.pauseStartedAtMs = void 0;
|
|
872
|
+
}
|
|
873
|
+
const elapsedMs = Math.max(0, Date.now() - activeRunTimer.startedAtMs - activeRunTimer.pausedMs);
|
|
874
|
+
const color = createColorizer();
|
|
875
|
+
const seconds = (elapsedMs / 1e3).toFixed(2);
|
|
876
|
+
if (exitCode === 0) {
|
|
877
|
+
writeSubtleInfo(`${color.green("\u2705")} Finished in ${seconds}s
|
|
878
|
+
`);
|
|
879
|
+
} else {
|
|
880
|
+
writeSubtleInfo(`${color.red("\u274C")} Finished in ${seconds}s
|
|
881
|
+
`);
|
|
882
|
+
}
|
|
883
|
+
activeRunTimer = void 0;
|
|
884
|
+
}
|
|
885
|
+
function pauseRunTimer() {
|
|
886
|
+
if (!activeRunTimer || activeRunTimer.pauseStartedAtMs !== void 0) {
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
activeRunTimer.pauseStartedAtMs = Date.now();
|
|
890
|
+
}
|
|
891
|
+
function resumeRunTimer() {
|
|
892
|
+
if (!activeRunTimer || activeRunTimer.pauseStartedAtMs === void 0) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
activeRunTimer.pausedMs += Date.now() - activeRunTimer.pauseStartedAtMs;
|
|
896
|
+
activeRunTimer.pauseStartedAtMs = void 0;
|
|
897
|
+
}
|
|
898
|
+
async function runPromptWithPausedTimer(prompt) {
|
|
899
|
+
pauseRunTimer();
|
|
900
|
+
try {
|
|
901
|
+
return await prompt();
|
|
902
|
+
} finally {
|
|
903
|
+
resumeRunTimer();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function readCliVersion() {
|
|
907
|
+
if (cachedCliVersion !== void 0) {
|
|
908
|
+
return cachedCliVersion;
|
|
909
|
+
}
|
|
910
|
+
const scriptPath = process.argv[1];
|
|
911
|
+
if (!scriptPath) {
|
|
912
|
+
cachedCliVersion = "unknown";
|
|
913
|
+
return cachedCliVersion;
|
|
914
|
+
}
|
|
915
|
+
let current = path.resolve(path.dirname(scriptPath));
|
|
916
|
+
while (true) {
|
|
917
|
+
const packageJsonPath = path.join(current, "package.json");
|
|
918
|
+
if (existsSync(packageJsonPath)) {
|
|
919
|
+
try {
|
|
920
|
+
const raw = readFileSync(packageJsonPath, "utf8");
|
|
921
|
+
const parsed = JSON.parse(raw);
|
|
922
|
+
cachedCliVersion = parsed.version ?? "unknown";
|
|
923
|
+
return cachedCliVersion;
|
|
924
|
+
} catch {
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
const parent = path.dirname(current);
|
|
929
|
+
if (parent === current) {
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
current = parent;
|
|
933
|
+
}
|
|
934
|
+
cachedCliVersion = "unknown";
|
|
935
|
+
return cachedCliVersion;
|
|
936
|
+
}
|
|
937
|
+
function writeRunContextHeader(cwd, commandLabel, configPath, storedSnapshots) {
|
|
938
|
+
if (!shouldShowRunLogs()) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
const color = createColorizer();
|
|
942
|
+
process.stdout.write(color.bold(`\u2728 eslint-config-snapshot v${readCliVersion()}
|
|
943
|
+
`));
|
|
944
|
+
process.stdout.write(`\u{1F9ED} Command: ${commandLabel}
|
|
945
|
+
`);
|
|
946
|
+
process.stdout.write(`\u{1F4C1} Repository: ${cwd}
|
|
947
|
+
`);
|
|
948
|
+
process.stdout.write(`\u2699\uFE0F Config source: ${formatConfigSource(cwd, configPath)}
|
|
949
|
+
`);
|
|
950
|
+
process.stdout.write(`\u{1F5C2}\uFE0F Baseline: ${formatStoredSnapshotSummary(storedSnapshots)}
|
|
951
|
+
|
|
952
|
+
`);
|
|
953
|
+
}
|
|
954
|
+
function formatConfigSource(cwd, configPath) {
|
|
955
|
+
if (!configPath) {
|
|
956
|
+
return "built-in defaults";
|
|
957
|
+
}
|
|
958
|
+
const rel = normalizePath(path.relative(cwd, configPath));
|
|
959
|
+
if (path.basename(configPath) === "package.json") {
|
|
960
|
+
return `${rel} (eslint-config-snapshot field)`;
|
|
961
|
+
}
|
|
962
|
+
return rel;
|
|
963
|
+
}
|
|
964
|
+
function formatStoredSnapshotSummary(storedSnapshots) {
|
|
965
|
+
if (storedSnapshots.size === 0) {
|
|
966
|
+
return "none";
|
|
967
|
+
}
|
|
968
|
+
const summary = summarizeStoredSnapshots(storedSnapshots);
|
|
969
|
+
return `${summary.groups} groups, ${summary.rules} rules (severity mix: ${summary.error} errors, ${summary.warn} warnings, ${summary.off} off)`;
|
|
970
|
+
}
|
|
971
|
+
async function resolveGroupEslintVersions(cwd) {
|
|
972
|
+
const config = await loadConfig(cwd);
|
|
973
|
+
const { discovery, assignments } = await resolveWorkspaceAssignments(cwd, config);
|
|
974
|
+
const result = /* @__PURE__ */ new Map();
|
|
975
|
+
for (const group of assignments) {
|
|
976
|
+
const versions = /* @__PURE__ */ new Set();
|
|
977
|
+
for (const workspaceRel of group.workspaces) {
|
|
978
|
+
const workspaceAbs = path.resolve(discovery.rootAbs, workspaceRel);
|
|
979
|
+
versions.add(resolveEslintVersionForWorkspace(workspaceAbs));
|
|
980
|
+
}
|
|
981
|
+
result.set(group.name, [...versions].sort((a, b) => a.localeCompare(b)));
|
|
982
|
+
}
|
|
983
|
+
return result;
|
|
984
|
+
}
|
|
985
|
+
function writeEslintVersionSummary(eslintVersionsByGroup) {
|
|
986
|
+
if (!shouldShowRunLogs() || eslintVersionsByGroup.size === 0) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const allVersions = /* @__PURE__ */ new Set();
|
|
990
|
+
for (const versions of eslintVersionsByGroup.values()) {
|
|
991
|
+
for (const version of versions) {
|
|
992
|
+
allVersions.add(version);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
const sortedAllVersions = [...allVersions].sort((a, b) => a.localeCompare(b));
|
|
996
|
+
if (sortedAllVersions.length === 1) {
|
|
997
|
+
process.stdout.write(`- eslint runtime: ${sortedAllVersions[0]} (all groups)
|
|
998
|
+
`);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
process.stdout.write("- eslint runtime by group:\n");
|
|
1002
|
+
const sortedEntries = [...eslintVersionsByGroup.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
1003
|
+
for (const [groupName, versions] of sortedEntries) {
|
|
1004
|
+
process.stdout.write(` - ${groupName}: ${versions.join(", ")}
|
|
1005
|
+
`);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function summarizeStoredSnapshots(snapshots) {
|
|
1009
|
+
const { rules, error, warn, off } = countRuleSeverities([...snapshots.values()].map((snapshot) => snapshot.rules));
|
|
1010
|
+
return { groups: snapshots.size, rules, error, warn, off };
|
|
1011
|
+
}
|
|
1012
|
+
function countRuleSeverities(ruleObjects) {
|
|
1013
|
+
let rules = 0;
|
|
1014
|
+
let error = 0;
|
|
1015
|
+
let warn = 0;
|
|
1016
|
+
let off = 0;
|
|
1017
|
+
for (const rulesObject of ruleObjects) {
|
|
1018
|
+
for (const entry of Object.values(rulesObject)) {
|
|
1019
|
+
rules += 1;
|
|
1020
|
+
if (entry[0] === "error") {
|
|
1021
|
+
error += 1;
|
|
1022
|
+
} else if (entry[0] === "warn") {
|
|
1023
|
+
warn += 1;
|
|
1024
|
+
} else {
|
|
1025
|
+
off += 1;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return { rules, error, warn, off };
|
|
1030
|
+
}
|
|
799
1031
|
function formatShortPrint(snapshots) {
|
|
800
1032
|
const lines = [];
|
|
801
1033
|
const sorted = [...snapshots].sort((a, b) => a.groupId.localeCompare(b.groupId));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-config-snapshot/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,6 +30,6 @@
|
|
|
30
30
|
"@inquirer/prompts": "^8.2.0",
|
|
31
31
|
"commander": "^14.0.3",
|
|
32
32
|
"fast-glob": "^3.3.3",
|
|
33
|
-
"@eslint-config-snapshot/api": "0.
|
|
33
|
+
"@eslint-config-snapshot/api": "0.6.0"
|
|
34
34
|
}
|
|
35
35
|
}
|