@eslint-config-snapshot/cli 1.3.0 โ 1.3.1
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 +8 -0
- package/dist/index.cjs +41 -17
- package/dist/index.js +41 -17
- package/package.json +2 -2
- package/src/commands/catalog.ts +18 -2
- package/src/formatters.ts +34 -1
- package/test/cli.terminal.integration.test.ts +5 -1
- package/test/formatters.unit.test.ts +31 -0
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -102,7 +102,7 @@ function summarizeChanges(changes) {
|
|
|
102
102
|
return { introduced, removed, severity, options, workspace };
|
|
103
103
|
}
|
|
104
104
|
function summarizeSnapshots(snapshots) {
|
|
105
|
-
const { rules, error, warn, off } =
|
|
105
|
+
const { rules, error, warn, off } = countUniqueRuleSeverities([...snapshots.values()].map((snapshot) => snapshot.rules));
|
|
106
106
|
return { groups: snapshots.size, rules, error, warn, off };
|
|
107
107
|
}
|
|
108
108
|
function countUniqueWorkspaces(snapshots) {
|
|
@@ -276,25 +276,34 @@ function formatBaselineSummaryLines(summary, workspaceCount) {
|
|
|
276
276
|
- \u{1F39A}\uFE0F severity mix: ${summary.error} errors, ${summary.warn} warnings, ${summary.off} off
|
|
277
277
|
`;
|
|
278
278
|
}
|
|
279
|
-
function
|
|
280
|
-
|
|
279
|
+
function countUniqueRuleSeverities(ruleObjects) {
|
|
280
|
+
const severityRank = { off: 0, warn: 1, error: 2 };
|
|
281
|
+
const severityByRule = /* @__PURE__ */ new Map();
|
|
282
|
+
for (const rulesObject of ruleObjects) {
|
|
283
|
+
for (const [ruleName, entry] of Object.entries(rulesObject)) {
|
|
284
|
+
const nextSeverity = getPrimarySeverity(entry);
|
|
285
|
+
if (!nextSeverity) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const currentSeverity = severityByRule.get(ruleName);
|
|
289
|
+
if (!currentSeverity || severityRank[nextSeverity] > severityRank[currentSeverity]) {
|
|
290
|
+
severityByRule.set(ruleName, nextSeverity);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
281
294
|
let error = 0;
|
|
282
295
|
let warn = 0;
|
|
283
296
|
let off = 0;
|
|
284
|
-
for (const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
warn += 1;
|
|
292
|
-
} else {
|
|
293
|
-
off += 1;
|
|
294
|
-
}
|
|
297
|
+
for (const severity of severityByRule.values()) {
|
|
298
|
+
if (severity === "error") {
|
|
299
|
+
error += 1;
|
|
300
|
+
} else if (severity === "warn") {
|
|
301
|
+
warn += 1;
|
|
302
|
+
} else {
|
|
303
|
+
off += 1;
|
|
295
304
|
}
|
|
296
305
|
}
|
|
297
|
-
return { rules, error, warn, off };
|
|
306
|
+
return { rules: severityByRule.size, error, warn, off };
|
|
298
307
|
}
|
|
299
308
|
function getPrimarySeverity(entry) {
|
|
300
309
|
if (!entry) {
|
|
@@ -871,10 +880,12 @@ async function executeCatalogUpdate(cwd, terminal, snapshotDir) {
|
|
|
871
880
|
const rows = await computeCatalogRows(cwd, terminal, snapshotDir, "catalog:update", false);
|
|
872
881
|
await writeCatalogBaselineFiles(cwd, snapshotDir, rows);
|
|
873
882
|
const groups = rows.length;
|
|
874
|
-
const available = rows.
|
|
875
|
-
const inUse = rows.
|
|
883
|
+
const available = countUniqueRules(rows.map((row) => row.availableRules));
|
|
884
|
+
const inUse = countUniqueRules(rows.map((row) => row.observedRules.filter((ruleName) => row.availableRules.includes(ruleName))));
|
|
876
885
|
terminal.write(`\u{1F9EA} Catalog baseline updated: ${groups} groups, ${available} available rules, ${inUse} currently in use.
|
|
877
886
|
`);
|
|
887
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
888
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
878
889
|
return 0;
|
|
879
890
|
}
|
|
880
891
|
async function executeCatalogCheck(cwd, terminal, snapshotDir) {
|
|
@@ -889,8 +900,12 @@ async function executeCatalogCheck(cwd, terminal, snapshotDir) {
|
|
|
889
900
|
const diffs = compareCatalogBaselines(stored, current);
|
|
890
901
|
if (diffs.length === 0) {
|
|
891
902
|
terminal.write("Great news: no catalog drift detected.\n");
|
|
903
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
904
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
892
905
|
return 0;
|
|
893
906
|
}
|
|
907
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
908
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
894
909
|
terminal.write(`\u26A0\uFE0F Heads up: catalog drift detected in ${diffs.length} groups.
|
|
895
910
|
`);
|
|
896
911
|
for (const diff of diffs) {
|
|
@@ -1131,6 +1146,15 @@ function toPercent(value, total) {
|
|
|
1131
1146
|
}
|
|
1132
1147
|
return Number((value / total * 100).toFixed(1));
|
|
1133
1148
|
}
|
|
1149
|
+
function countUniqueRules(ruleLists) {
|
|
1150
|
+
const unique = /* @__PURE__ */ new Set();
|
|
1151
|
+
for (const rules of ruleLists) {
|
|
1152
|
+
for (const rule of rules) {
|
|
1153
|
+
unique.add(rule);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return unique.size;
|
|
1157
|
+
}
|
|
1134
1158
|
|
|
1135
1159
|
// src/commands/check.ts
|
|
1136
1160
|
var UPDATE_HINT = "Tip: when you intentionally accept changes, run `eslint-config-snapshot --update` to refresh the baseline.\n";
|
package/dist/index.js
CHANGED
|
@@ -67,7 +67,7 @@ function summarizeChanges(changes) {
|
|
|
67
67
|
return { introduced, removed, severity, options, workspace };
|
|
68
68
|
}
|
|
69
69
|
function summarizeSnapshots(snapshots) {
|
|
70
|
-
const { rules, error, warn, off } =
|
|
70
|
+
const { rules, error, warn, off } = countUniqueRuleSeverities([...snapshots.values()].map((snapshot) => snapshot.rules));
|
|
71
71
|
return { groups: snapshots.size, rules, error, warn, off };
|
|
72
72
|
}
|
|
73
73
|
function countUniqueWorkspaces(snapshots) {
|
|
@@ -241,25 +241,34 @@ function formatBaselineSummaryLines(summary, workspaceCount) {
|
|
|
241
241
|
- \u{1F39A}\uFE0F severity mix: ${summary.error} errors, ${summary.warn} warnings, ${summary.off} off
|
|
242
242
|
`;
|
|
243
243
|
}
|
|
244
|
-
function
|
|
245
|
-
|
|
244
|
+
function countUniqueRuleSeverities(ruleObjects) {
|
|
245
|
+
const severityRank = { off: 0, warn: 1, error: 2 };
|
|
246
|
+
const severityByRule = /* @__PURE__ */ new Map();
|
|
247
|
+
for (const rulesObject of ruleObjects) {
|
|
248
|
+
for (const [ruleName, entry] of Object.entries(rulesObject)) {
|
|
249
|
+
const nextSeverity = getPrimarySeverity(entry);
|
|
250
|
+
if (!nextSeverity) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const currentSeverity = severityByRule.get(ruleName);
|
|
254
|
+
if (!currentSeverity || severityRank[nextSeverity] > severityRank[currentSeverity]) {
|
|
255
|
+
severityByRule.set(ruleName, nextSeverity);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
246
259
|
let error = 0;
|
|
247
260
|
let warn = 0;
|
|
248
261
|
let off = 0;
|
|
249
|
-
for (const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
warn += 1;
|
|
257
|
-
} else {
|
|
258
|
-
off += 1;
|
|
259
|
-
}
|
|
262
|
+
for (const severity of severityByRule.values()) {
|
|
263
|
+
if (severity === "error") {
|
|
264
|
+
error += 1;
|
|
265
|
+
} else if (severity === "warn") {
|
|
266
|
+
warn += 1;
|
|
267
|
+
} else {
|
|
268
|
+
off += 1;
|
|
260
269
|
}
|
|
261
270
|
}
|
|
262
|
-
return { rules, error, warn, off };
|
|
271
|
+
return { rules: severityByRule.size, error, warn, off };
|
|
263
272
|
}
|
|
264
273
|
function getPrimarySeverity(entry) {
|
|
265
274
|
if (!entry) {
|
|
@@ -850,10 +859,12 @@ async function executeCatalogUpdate(cwd, terminal, snapshotDir) {
|
|
|
850
859
|
const rows = await computeCatalogRows(cwd, terminal, snapshotDir, "catalog:update", false);
|
|
851
860
|
await writeCatalogBaselineFiles(cwd, snapshotDir, rows);
|
|
852
861
|
const groups = rows.length;
|
|
853
|
-
const available = rows.
|
|
854
|
-
const inUse = rows.
|
|
862
|
+
const available = countUniqueRules(rows.map((row) => row.availableRules));
|
|
863
|
+
const inUse = countUniqueRules(rows.map((row) => row.observedRules.filter((ruleName) => row.availableRules.includes(ruleName))));
|
|
855
864
|
terminal.write(`\u{1F9EA} Catalog baseline updated: ${groups} groups, ${available} available rules, ${inUse} currently in use.
|
|
856
865
|
`);
|
|
866
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
867
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
857
868
|
return 0;
|
|
858
869
|
}
|
|
859
870
|
async function executeCatalogCheck(cwd, terminal, snapshotDir) {
|
|
@@ -868,8 +879,12 @@ async function executeCatalogCheck(cwd, terminal, snapshotDir) {
|
|
|
868
879
|
const diffs = compareCatalogBaselines(stored, current);
|
|
869
880
|
if (diffs.length === 0) {
|
|
870
881
|
terminal.write("Great news: no catalog drift detected.\n");
|
|
882
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
883
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
871
884
|
return 0;
|
|
872
885
|
}
|
|
886
|
+
terminal.section("\u{1F4CA} Catalog summary");
|
|
887
|
+
terminal.write(formatShortCatalog(rows, false));
|
|
873
888
|
terminal.write(`\u26A0\uFE0F Heads up: catalog drift detected in ${diffs.length} groups.
|
|
874
889
|
`);
|
|
875
890
|
for (const diff of diffs) {
|
|
@@ -1110,6 +1125,15 @@ function toPercent(value, total) {
|
|
|
1110
1125
|
}
|
|
1111
1126
|
return Number((value / total * 100).toFixed(1));
|
|
1112
1127
|
}
|
|
1128
|
+
function countUniqueRules(ruleLists) {
|
|
1129
|
+
const unique = /* @__PURE__ */ new Set();
|
|
1130
|
+
for (const rules of ruleLists) {
|
|
1131
|
+
for (const rule of rules) {
|
|
1132
|
+
unique.add(rule);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return unique.size;
|
|
1136
|
+
}
|
|
1113
1137
|
|
|
1114
1138
|
// src/commands/check.ts
|
|
1115
1139
|
var UPDATE_HINT = "Tip: when you intentionally accept changes, run `eslint-config-snapshot --update` to refresh the baseline.\n";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-config-snapshot/cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"commander": "^14.0.3",
|
|
32
32
|
"debug": "^4.4.3",
|
|
33
33
|
"fast-glob": "^3.3.3",
|
|
34
|
-
"@eslint-config-snapshot/api": "1.3.
|
|
34
|
+
"@eslint-config-snapshot/api": "1.3.1"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/commands/catalog.ts
CHANGED
|
@@ -87,9 +87,11 @@ export async function executeCatalogUpdate(cwd: string, terminal: TerminalIO, sn
|
|
|
87
87
|
await writeCatalogBaselineFiles(cwd, snapshotDir, rows)
|
|
88
88
|
|
|
89
89
|
const groups = rows.length
|
|
90
|
-
const available = rows.
|
|
91
|
-
const inUse = rows.
|
|
90
|
+
const available = countUniqueRules(rows.map((row) => row.availableRules))
|
|
91
|
+
const inUse = countUniqueRules(rows.map((row) => row.observedRules.filter((ruleName) => row.availableRules.includes(ruleName))))
|
|
92
92
|
terminal.write(`๐งช Catalog baseline updated: ${groups} groups, ${available} available rules, ${inUse} currently in use.\n`)
|
|
93
|
+
terminal.section('๐ Catalog summary')
|
|
94
|
+
terminal.write(formatShortCatalog(rows, false))
|
|
93
95
|
return 0
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -107,9 +109,13 @@ export async function executeCatalogCheck(cwd: string, terminal: TerminalIO, sna
|
|
|
107
109
|
const diffs = compareCatalogBaselines(stored, current)
|
|
108
110
|
if (diffs.length === 0) {
|
|
109
111
|
terminal.write('Great news: no catalog drift detected.\n')
|
|
112
|
+
terminal.section('๐ Catalog summary')
|
|
113
|
+
terminal.write(formatShortCatalog(rows, false))
|
|
110
114
|
return 0
|
|
111
115
|
}
|
|
112
116
|
|
|
117
|
+
terminal.section('๐ Catalog summary')
|
|
118
|
+
terminal.write(formatShortCatalog(rows, false))
|
|
113
119
|
terminal.write(`โ ๏ธ Heads up: catalog drift detected in ${diffs.length} groups.\n`)
|
|
114
120
|
for (const diff of diffs) {
|
|
115
121
|
terminal.write(
|
|
@@ -392,3 +398,13 @@ function toPercent(value: number, total: number): number {
|
|
|
392
398
|
}
|
|
393
399
|
return Number(((value / total) * 100).toFixed(1))
|
|
394
400
|
}
|
|
401
|
+
|
|
402
|
+
function countUniqueRules(ruleLists: string[][]): number {
|
|
403
|
+
const unique = new Set<string>()
|
|
404
|
+
for (const rules of ruleLists) {
|
|
405
|
+
for (const rule of rules) {
|
|
406
|
+
unique.add(rule)
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return unique.size
|
|
410
|
+
}
|
package/src/formatters.ts
CHANGED
|
@@ -101,7 +101,7 @@ export function summarizeChanges(changes: Array<{ groupId: string; diff: Snapsho
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
export function summarizeSnapshots(snapshots: Map<string, SnapshotLike>) {
|
|
104
|
-
const { rules, error, warn, off } =
|
|
104
|
+
const { rules, error, warn, off } = countUniqueRuleSeverities([...snapshots.values()].map((snapshot) => snapshot.rules))
|
|
105
105
|
return { groups: snapshots.size, rules, error, warn, off }
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -331,6 +331,39 @@ export function countRuleSeverities(ruleObjects: RuleObject[]) {
|
|
|
331
331
|
return { rules, error, warn, off }
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
export function countUniqueRuleSeverities(ruleObjects: RuleObject[]) {
|
|
335
|
+
const severityRank: Record<'off' | 'warn' | 'error', number> = { off: 0, warn: 1, error: 2 }
|
|
336
|
+
const severityByRule = new Map<string, 'off' | 'warn' | 'error'>()
|
|
337
|
+
|
|
338
|
+
for (const rulesObject of ruleObjects) {
|
|
339
|
+
for (const [ruleName, entry] of Object.entries(rulesObject)) {
|
|
340
|
+
const nextSeverity = getPrimarySeverity(entry)
|
|
341
|
+
if (!nextSeverity) {
|
|
342
|
+
continue
|
|
343
|
+
}
|
|
344
|
+
const currentSeverity = severityByRule.get(ruleName)
|
|
345
|
+
if (!currentSeverity || severityRank[nextSeverity] > severityRank[currentSeverity]) {
|
|
346
|
+
severityByRule.set(ruleName, nextSeverity)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let error = 0
|
|
352
|
+
let warn = 0
|
|
353
|
+
let off = 0
|
|
354
|
+
for (const severity of severityByRule.values()) {
|
|
355
|
+
if (severity === 'error') {
|
|
356
|
+
error += 1
|
|
357
|
+
} else if (severity === 'warn') {
|
|
358
|
+
warn += 1
|
|
359
|
+
} else {
|
|
360
|
+
off += 1
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return { rules: severityByRule.size, error, warn, off }
|
|
365
|
+
}
|
|
366
|
+
|
|
334
367
|
function getPrimarySeverity(entry: SnapshotRuleEntry | undefined): 'off' | 'warn' | 'error' | undefined {
|
|
335
368
|
if (!entry) {
|
|
336
369
|
return undefined
|
|
@@ -266,11 +266,15 @@ no-debugger: off
|
|
|
266
266
|
const update = run(['catalog-update'])
|
|
267
267
|
expect(update.status).toBe(0)
|
|
268
268
|
expect(update.stdout).toContain('Catalog baseline updated:')
|
|
269
|
+
expect(update.stdout).toContain('๐ฆ total:')
|
|
270
|
+
expect(update.stdout).toContain('๐ plugins tracked:')
|
|
269
271
|
expect(update.stderr).toBe('')
|
|
270
272
|
|
|
271
273
|
const check = run(['catalog-check'])
|
|
272
274
|
expect(check.status).toBe(0)
|
|
273
|
-
expect(check.stdout).
|
|
275
|
+
expect(check.stdout).toContain('Great news: no catalog drift detected.')
|
|
276
|
+
expect(check.stdout).toContain('๐ฆ total:')
|
|
277
|
+
expect(check.stdout).toContain('๐ plugins tracked:')
|
|
274
278
|
expect(check.stderr).toBe('')
|
|
275
279
|
})
|
|
276
280
|
|
|
@@ -44,4 +44,35 @@ describe('output helpers', () => {
|
|
|
44
44
|
)
|
|
45
45
|
expect(summary).toEqual({ groups: 1, rules: 3, error: 1, warn: 1, off: 1 })
|
|
46
46
|
})
|
|
47
|
+
|
|
48
|
+
it('deduplicates rules across groups in summary', () => {
|
|
49
|
+
const summary = summarizeSnapshots(
|
|
50
|
+
new Map([
|
|
51
|
+
[
|
|
52
|
+
'group-a',
|
|
53
|
+
{
|
|
54
|
+
groupId: 'group-a',
|
|
55
|
+
workspaces: ['packages/a'],
|
|
56
|
+
rules: {
|
|
57
|
+
shared: ['warn'],
|
|
58
|
+
onlyA: ['off']
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
[
|
|
63
|
+
'group-b',
|
|
64
|
+
{
|
|
65
|
+
groupId: 'group-b',
|
|
66
|
+
workspaces: ['packages/b'],
|
|
67
|
+
rules: {
|
|
68
|
+
shared: ['error'],
|
|
69
|
+
onlyB: ['warn']
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
])
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
expect(summary).toEqual({ groups: 2, rules: 3, error: 1, warn: 1, off: 1 })
|
|
77
|
+
})
|
|
47
78
|
})
|