@kevinrabun/judges 3.55.0 → 3.56.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 +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/api-versioning-audit.d.ts +6 -0
- package/dist/commands/api-versioning-audit.d.ts.map +1 -0
- package/dist/commands/api-versioning-audit.js +234 -0
- package/dist/commands/api-versioning-audit.js.map +1 -0
- package/dist/commands/boundary-enforce.d.ts +6 -0
- package/dist/commands/boundary-enforce.d.ts.map +1 -0
- package/dist/commands/boundary-enforce.js +256 -0
- package/dist/commands/boundary-enforce.js.map +1 -0
- package/dist/commands/error-taxonomy.d.ts +6 -0
- package/dist/commands/error-taxonomy.d.ts.map +1 -0
- package/dist/commands/error-taxonomy.js +227 -0
- package/dist/commands/error-taxonomy.js.map +1 -0
- package/dist/commands/log-quality.d.ts +6 -0
- package/dist/commands/log-quality.d.ts.map +1 -0
- package/dist/commands/log-quality.js +212 -0
- package/dist/commands/log-quality.js.map +1 -0
- package/dist/commands/null-safety-audit.d.ts +6 -0
- package/dist/commands/null-safety-audit.d.ts.map +1 -0
- package/dist/commands/null-safety-audit.js +222 -0
- package/dist/commands/null-safety-audit.js.map +1 -0
- package/dist/commands/ownership-map.d.ts +6 -0
- package/dist/commands/ownership-map.d.ts.map +1 -0
- package/dist/commands/ownership-map.js +229 -0
- package/dist/commands/ownership-map.js.map +1 -0
- package/dist/commands/retry-pattern-audit.d.ts +6 -0
- package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
- package/dist/commands/retry-pattern-audit.js +216 -0
- package/dist/commands/retry-pattern-audit.js.map +1 -0
- package/dist/commands/test-isolation.d.ts +6 -0
- package/dist/commands/test-isolation.d.ts.map +1 -0
- package/dist/commands/test-isolation.js +235 -0
- package/dist/commands/test-isolation.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error taxonomy — classify and standardize error codes, messages, and
|
|
3
|
+
* hierarchies across a codebase.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
6
|
+
import { join, extname } from "path";
|
|
7
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
8
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
|
|
9
|
+
function collectFiles(dir, max = 300) {
|
|
10
|
+
const files = [];
|
|
11
|
+
function walk(d) {
|
|
12
|
+
if (files.length >= max)
|
|
13
|
+
return;
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = readdirSync(d);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (files.length >= max)
|
|
23
|
+
return;
|
|
24
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
25
|
+
continue;
|
|
26
|
+
const full = join(d, e);
|
|
27
|
+
try {
|
|
28
|
+
if (statSync(full).isDirectory())
|
|
29
|
+
walk(full);
|
|
30
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
31
|
+
files.push(full);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* skip */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
walk(dir);
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
// ─── Extraction ─────────────────────────────────────────────────────────────
|
|
42
|
+
function extractErrors(filepath) {
|
|
43
|
+
const errors = [];
|
|
44
|
+
let content;
|
|
45
|
+
try {
|
|
46
|
+
content = readFileSync(filepath, "utf-8");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return errors;
|
|
50
|
+
}
|
|
51
|
+
const lines = content.split("\n");
|
|
52
|
+
for (let i = 0; i < lines.length; i++) {
|
|
53
|
+
const line = lines[i];
|
|
54
|
+
// Error class definitions
|
|
55
|
+
const classMatch = line.match(/class\s+(\w*Error\w*)\s+extends/);
|
|
56
|
+
if (classMatch) {
|
|
57
|
+
errors.push({ file: filepath, line: i + 1, code: classMatch[1], message: "", kind: "class" });
|
|
58
|
+
}
|
|
59
|
+
// Error code constants
|
|
60
|
+
const constMatch = line.match(/(?:const|export\s+const|static\s+readonly)\s+(\w*(?:ERR|ERROR|CODE)\w*)\s*[:=]\s*['"]([^'"]+)['"]/i);
|
|
61
|
+
if (constMatch) {
|
|
62
|
+
errors.push({ file: filepath, line: i + 1, code: constMatch[1], message: constMatch[2], kind: "constant" });
|
|
63
|
+
}
|
|
64
|
+
// throw new Error
|
|
65
|
+
const throwMatch = line.match(/throw\s+new\s+(\w*Error)\s*\(\s*['"`]([^'"`]{3,}?)['"`]/);
|
|
66
|
+
if (throwMatch) {
|
|
67
|
+
errors.push({ file: filepath, line: i + 1, code: throwMatch[1], message: throwMatch[2], kind: "throw" });
|
|
68
|
+
}
|
|
69
|
+
// HTTP status codes in responses
|
|
70
|
+
const statusMatch = line.match(/(?:status|statusCode|res\.status)\s*[:=(]\s*(\d{3})/);
|
|
71
|
+
if (statusMatch) {
|
|
72
|
+
const msgMatch = line.match(/(?:message|msg|error)\s*[:=]\s*['"`]([^'"`]+)['"`]/);
|
|
73
|
+
errors.push({
|
|
74
|
+
file: filepath,
|
|
75
|
+
line: i + 1,
|
|
76
|
+
code: `HTTP_${statusMatch[1]}`,
|
|
77
|
+
message: msgMatch?.[1] || "",
|
|
78
|
+
kind: "status",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return errors;
|
|
83
|
+
}
|
|
84
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
85
|
+
function analyzeErrors(allErrors) {
|
|
86
|
+
const issues = [];
|
|
87
|
+
// Duplicate error messages
|
|
88
|
+
const msgMap = new Map();
|
|
89
|
+
for (const e of allErrors) {
|
|
90
|
+
if (e.message) {
|
|
91
|
+
const key = e.message.toLowerCase().trim();
|
|
92
|
+
if (!msgMap.has(key))
|
|
93
|
+
msgMap.set(key, []);
|
|
94
|
+
msgMap.get(key).push(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const dupes = [...msgMap.entries()].filter(([, v]) => v.length > 1);
|
|
98
|
+
if (dupes.length > 0) {
|
|
99
|
+
issues.push({
|
|
100
|
+
issue: `${dupes.length} duplicate error message(s)`,
|
|
101
|
+
severity: "medium",
|
|
102
|
+
detail: "Same message thrown from multiple places — consolidate into error constants",
|
|
103
|
+
examples: dupes.slice(0, 5).map(([msg, defs]) => `"${msg}" in ${defs.length} places`),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Inconsistent naming
|
|
107
|
+
const errorClasses = allErrors.filter((e) => e.kind === "class").map((e) => e.code);
|
|
108
|
+
const mixedCase = errorClasses.filter((c) => /Error$/i.test(c) && !/Error$/.test(c));
|
|
109
|
+
if (mixedCase.length > 0) {
|
|
110
|
+
issues.push({
|
|
111
|
+
issue: "Inconsistent error class naming",
|
|
112
|
+
severity: "low",
|
|
113
|
+
detail: "Some error classes don't follow PascalCase + Error suffix convention",
|
|
114
|
+
examples: mixedCase.slice(0, 5),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Bare Error throws (no custom class)
|
|
118
|
+
const bareThrows = allErrors.filter((e) => e.kind === "throw" && e.code === "Error");
|
|
119
|
+
if (bareThrows.length > 5) {
|
|
120
|
+
issues.push({
|
|
121
|
+
issue: `${bareThrows.length} bare Error throws`,
|
|
122
|
+
severity: "high",
|
|
123
|
+
detail: "Throwing plain Error makes catch handling harder — use typed error classes",
|
|
124
|
+
examples: bareThrows.slice(0, 5).map((e) => `${e.file}:${e.line} — "${e.message.slice(0, 50)}"`),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// Missing error codes
|
|
128
|
+
const constants = allErrors.filter((e) => e.kind === "constant");
|
|
129
|
+
const throws = allErrors.filter((e) => e.kind === "throw");
|
|
130
|
+
if (throws.length > 10 && constants.length === 0) {
|
|
131
|
+
issues.push({
|
|
132
|
+
issue: "No error code constants",
|
|
133
|
+
severity: "high",
|
|
134
|
+
detail: "Define error codes for machine-readable error handling (e.g., ERR_AUTH_FAILED)",
|
|
135
|
+
examples: throws.slice(0, 3).map((t) => `${t.file}:${t.line}`),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Inconsistent HTTP status usage
|
|
139
|
+
const statusDefs = allErrors.filter((e) => e.kind === "status");
|
|
140
|
+
const statusCodes = new Map();
|
|
141
|
+
for (const s of statusDefs) {
|
|
142
|
+
statusCodes.set(s.code, (statusCodes.get(s.code) || 0) + 1);
|
|
143
|
+
}
|
|
144
|
+
const overusedStatuses = [...statusCodes.entries()].filter(([, count]) => count > 10);
|
|
145
|
+
if (overusedStatuses.length > 0) {
|
|
146
|
+
issues.push({
|
|
147
|
+
issue: "HTTP status code overuse",
|
|
148
|
+
severity: "medium",
|
|
149
|
+
detail: "Same status code used extensively — consider more specific error responses",
|
|
150
|
+
examples: overusedStatuses.map(([code, count]) => `${code} used ${count} times`),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Generic messages
|
|
154
|
+
const genericMsgs = allErrors.filter((e) => e.message && /^(error|something went wrong|unknown error|internal error|failed)$/i.test(e.message.trim()));
|
|
155
|
+
if (genericMsgs.length > 0) {
|
|
156
|
+
issues.push({
|
|
157
|
+
issue: `${genericMsgs.length} generic error message(s)`,
|
|
158
|
+
severity: "high",
|
|
159
|
+
detail: "Vague error messages impede debugging — include context (what failed, why, and what to try)",
|
|
160
|
+
examples: genericMsgs.slice(0, 5).map((e) => `${e.file}:${e.line} — "${e.message}"`),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return issues;
|
|
164
|
+
}
|
|
165
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
166
|
+
export function runErrorTaxonomy(argv) {
|
|
167
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
168
|
+
console.log(`
|
|
169
|
+
judges error-taxonomy — Classify and standardize error codes and messages
|
|
170
|
+
|
|
171
|
+
Usage:
|
|
172
|
+
judges error-taxonomy [dir]
|
|
173
|
+
judges error-taxonomy src/ --format json
|
|
174
|
+
|
|
175
|
+
Options:
|
|
176
|
+
[dir] Directory to scan (default: .)
|
|
177
|
+
--format json JSON output
|
|
178
|
+
--help, -h Show this help
|
|
179
|
+
|
|
180
|
+
Checks: duplicate messages, inconsistent naming, bare Error throws, missing error codes,
|
|
181
|
+
generic messages, HTTP status overuse.
|
|
182
|
+
`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
186
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
187
|
+
const files = collectFiles(dir);
|
|
188
|
+
const allErrors = [];
|
|
189
|
+
for (const f of files)
|
|
190
|
+
allErrors.push(...extractErrors(f));
|
|
191
|
+
const issues = analyzeErrors(allErrors);
|
|
192
|
+
const highCount = issues.filter((i) => i.severity === "high").length;
|
|
193
|
+
const score = Math.max(0, 100 - highCount * 15 - issues.length * 5);
|
|
194
|
+
if (format === "json") {
|
|
195
|
+
console.log(JSON.stringify({
|
|
196
|
+
errors: allErrors.length,
|
|
197
|
+
issues,
|
|
198
|
+
score,
|
|
199
|
+
summary: {
|
|
200
|
+
classes: allErrors.filter((e) => e.kind === "class").length,
|
|
201
|
+
constants: allErrors.filter((e) => e.kind === "constant").length,
|
|
202
|
+
throws: allErrors.filter((e) => e.kind === "throw").length,
|
|
203
|
+
issues: issues.length,
|
|
204
|
+
},
|
|
205
|
+
timestamp: new Date().toISOString(),
|
|
206
|
+
}, null, 2));
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const badge = score >= 80 ? "✅ CONSISTENT" : score >= 50 ? "⚠️ INCONSISTENT" : "❌ CHAOTIC";
|
|
210
|
+
console.log(`\n Error Taxonomy: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
211
|
+
console.log(` Error definitions: ${allErrors.length} | Classes: ${allErrors.filter((e) => e.kind === "class").length} | Constants: ${allErrors.filter((e) => e.kind === "constant").length} | Throws: ${allErrors.filter((e) => e.kind === "throw").length}\n`);
|
|
212
|
+
if (issues.length === 0) {
|
|
213
|
+
console.log(" No taxonomy issues detected.\n");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
for (const issue of issues) {
|
|
217
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
218
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
219
|
+
console.log(` ${issue.detail}`);
|
|
220
|
+
for (const ex of issue.examples) {
|
|
221
|
+
console.log(` • ${ex}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
console.log(`\n Score: ${score}/100\n`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=error-taxonomy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-taxonomy.js","sourceRoot":"","sources":["../../src/commands/error-taxonomy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-quality.d.ts","sourceRoot":"","sources":["../../src/commands/log-quality.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA+KH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DlD"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log quality — assess logging hygiene: structured format consistency,
|
|
3
|
+
* PII leaks, level correctness, and coverage gaps.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
6
|
+
import { join, extname } from "path";
|
|
7
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
8
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
|
|
9
|
+
function collectFiles(dir, max = 300) {
|
|
10
|
+
const files = [];
|
|
11
|
+
function walk(d) {
|
|
12
|
+
if (files.length >= max)
|
|
13
|
+
return;
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = readdirSync(d);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (files.length >= max)
|
|
23
|
+
return;
|
|
24
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
25
|
+
continue;
|
|
26
|
+
const full = join(d, e);
|
|
27
|
+
try {
|
|
28
|
+
if (statSync(full).isDirectory())
|
|
29
|
+
walk(full);
|
|
30
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
31
|
+
files.push(full);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* skip */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
walk(dir);
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
42
|
+
const PII_PATTERNS = [
|
|
43
|
+
{ pattern: /(?:email|e-mail|user_?email)\s*[:=]/i, name: "email" },
|
|
44
|
+
{ pattern: /(?:password|passwd|pwd|secret)\s*[:=]/i, name: "password" },
|
|
45
|
+
{ pattern: /(?:ssn|social.?security|national.?id)\s*[:=]/i, name: "SSN/national ID" },
|
|
46
|
+
{ pattern: /(?:credit.?card|card.?number|ccn)\s*[:=]/i, name: "credit card" },
|
|
47
|
+
{ pattern: /(?:phone.?number|mobile|cell)\s*[:=]/i, name: "phone number" },
|
|
48
|
+
{ pattern: /(?:date.?of.?birth|dob|birthday)\s*[:=]/i, name: "date of birth" },
|
|
49
|
+
{ pattern: /(?:ip.?address|client.?ip|remote.?addr)\s*[:=]/i, name: "IP address" },
|
|
50
|
+
];
|
|
51
|
+
function analyzeFile(filepath) {
|
|
52
|
+
const issues = [];
|
|
53
|
+
let content;
|
|
54
|
+
try {
|
|
55
|
+
content = readFileSync(filepath, "utf-8");
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return issues;
|
|
59
|
+
}
|
|
60
|
+
const lines = content.split("\n");
|
|
61
|
+
const isTestFile = /\.test\.|\.spec\.|__test__/i.test(filepath);
|
|
62
|
+
if (isTestFile)
|
|
63
|
+
return issues;
|
|
64
|
+
for (let i = 0; i < lines.length; i++) {
|
|
65
|
+
const line = lines[i];
|
|
66
|
+
// Console.log in production code
|
|
67
|
+
if (/console\.log\s*\(/.test(line) && !/\/\//.test(line.split("console")[0])) {
|
|
68
|
+
issues.push({
|
|
69
|
+
file: filepath,
|
|
70
|
+
line: i + 1,
|
|
71
|
+
issue: "console.log in production code",
|
|
72
|
+
severity: "medium",
|
|
73
|
+
suggestion: "Use a structured logger (winston, pino, bunyan)",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Wrong log level
|
|
77
|
+
if (/console\.log\s*\(\s*['"`](?:error|err|fail|exception|crash)/i.test(line)) {
|
|
78
|
+
issues.push({
|
|
79
|
+
file: filepath,
|
|
80
|
+
line: i + 1,
|
|
81
|
+
issue: "Error logged at info/debug level",
|
|
82
|
+
severity: "high",
|
|
83
|
+
suggestion: "Use console.error or logger.error for error conditions",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (/(?:logger|log)\.(?:debug|info|trace)\s*\(\s*['"`](?:error|fail|exception|crash)/i.test(line)) {
|
|
87
|
+
issues.push({
|
|
88
|
+
file: filepath,
|
|
89
|
+
line: i + 1,
|
|
90
|
+
issue: "Error logged at info/debug level",
|
|
91
|
+
severity: "high",
|
|
92
|
+
suggestion: "Use logger.error() for error conditions",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// String interpolation in structured logger
|
|
96
|
+
if (/(?:logger|log)\.\w+\s*\(\s*`/.test(line)) {
|
|
97
|
+
issues.push({
|
|
98
|
+
file: filepath,
|
|
99
|
+
line: i + 1,
|
|
100
|
+
issue: "Template literal in structured logger",
|
|
101
|
+
severity: "medium",
|
|
102
|
+
suggestion: "Use structured fields: logger.info('msg', { key: value }) for queryability",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// PII in log statements
|
|
106
|
+
if (/(?:console|log|logger)\.\w+\s*\(/.test(line)) {
|
|
107
|
+
for (const pii of PII_PATTERNS) {
|
|
108
|
+
if (pii.pattern.test(line)) {
|
|
109
|
+
issues.push({
|
|
110
|
+
file: filepath,
|
|
111
|
+
line: i + 1,
|
|
112
|
+
issue: `Potential ${pii.name} in log output`,
|
|
113
|
+
severity: "high",
|
|
114
|
+
suggestion: "Mask or redact PII before logging — may violate GDPR/CCPA",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Logging full objects/errors without selection
|
|
120
|
+
if (/(?:console|log|logger)\.\w+\s*\(\s*(?:err|error|exception|e)\s*\)/.test(line)) {
|
|
121
|
+
issues.push({
|
|
122
|
+
file: filepath,
|
|
123
|
+
line: i + 1,
|
|
124
|
+
issue: "Logging full error object",
|
|
125
|
+
severity: "low",
|
|
126
|
+
suggestion: "Log error.message and error.stack separately for structured parsing",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Log statements with string concatenation (not structured)
|
|
130
|
+
if (/(?:console|log|logger)\.\w+\s*\(\s*['"].*['"]\s*\+/.test(line)) {
|
|
131
|
+
issues.push({
|
|
132
|
+
file: filepath,
|
|
133
|
+
line: i + 1,
|
|
134
|
+
issue: "String concatenation in log",
|
|
135
|
+
severity: "low",
|
|
136
|
+
suggestion: "Use structured logging with key-value pairs",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Check for catch blocks without logging
|
|
141
|
+
for (let i = 0; i < lines.length; i++) {
|
|
142
|
+
if (/\bcatch\s*\(/.test(lines[i])) {
|
|
143
|
+
const block = lines.slice(i, Math.min(i + 8, lines.length)).join("\n");
|
|
144
|
+
if (!/log|logger|console\.(error|warn|log)|print|println/i.test(block) && !/throw|rethrow|reject/i.test(block)) {
|
|
145
|
+
issues.push({
|
|
146
|
+
file: filepath,
|
|
147
|
+
line: i + 1,
|
|
148
|
+
issue: "Silent catch block",
|
|
149
|
+
severity: "high",
|
|
150
|
+
suggestion: "Log errors in catch blocks or explicitly re-throw",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return issues;
|
|
156
|
+
}
|
|
157
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
158
|
+
export function runLogQuality(argv) {
|
|
159
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
160
|
+
console.log(`
|
|
161
|
+
judges log-quality — Assess logging hygiene and quality
|
|
162
|
+
|
|
163
|
+
Usage:
|
|
164
|
+
judges log-quality [dir]
|
|
165
|
+
judges log-quality src/ --format json
|
|
166
|
+
|
|
167
|
+
Options:
|
|
168
|
+
[dir] Directory to scan (default: .)
|
|
169
|
+
--format json JSON output
|
|
170
|
+
--help, -h Show this help
|
|
171
|
+
|
|
172
|
+
Checks: wrong log levels, PII in logs, unstructured logging, string concatenation,
|
|
173
|
+
template literals in structured loggers, silent catch blocks.
|
|
174
|
+
`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
178
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
179
|
+
const files = collectFiles(dir);
|
|
180
|
+
const allIssues = [];
|
|
181
|
+
for (const f of files)
|
|
182
|
+
allIssues.push(...analyzeFile(f));
|
|
183
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
184
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
185
|
+
const score = Math.max(0, 100 - highCount * 10 - medCount * 3);
|
|
186
|
+
if (format === "json") {
|
|
187
|
+
console.log(JSON.stringify({
|
|
188
|
+
issues: allIssues,
|
|
189
|
+
score,
|
|
190
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
191
|
+
timestamp: new Date().toISOString(),
|
|
192
|
+
}, null, 2));
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
const badge = score >= 80 ? "✅ GOOD" : score >= 50 ? "⚠️ NEEDS WORK" : "❌ POOR";
|
|
196
|
+
console.log(`\n Log Quality: ${badge} (${score}/100)\n ─────────────────────────`);
|
|
197
|
+
if (allIssues.length === 0) {
|
|
198
|
+
console.log(" No logging issues detected.\n");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
202
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
203
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
204
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
205
|
+
console.log(` → ${issue.suggestion}`);
|
|
206
|
+
}
|
|
207
|
+
if (allIssues.length > 25)
|
|
208
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
209
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=log-quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-quality.js","sourceRoot":"","sources":["../../src/commands/log-quality.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-safety-audit.d.ts","sourceRoot":"","sources":["../../src/commands/null-safety-audit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4LH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DvD"}
|