@kevinrabun/judges 1.2.0 → 1.4.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 +49 -13
- package/dist/evaluators/authentication.d.ts +3 -0
- package/dist/evaluators/authentication.d.ts.map +1 -0
- package/dist/evaluators/authentication.js +170 -0
- package/dist/evaluators/authentication.js.map +1 -0
- package/dist/evaluators/backwards-compatibility.d.ts +3 -0
- package/dist/evaluators/backwards-compatibility.d.ts.map +1 -0
- package/dist/evaluators/backwards-compatibility.js +146 -0
- package/dist/evaluators/backwards-compatibility.js.map +1 -0
- package/dist/evaluators/caching.d.ts +3 -0
- package/dist/evaluators/caching.d.ts.map +1 -0
- package/dist/evaluators/caching.js +146 -0
- package/dist/evaluators/caching.js.map +1 -0
- package/dist/evaluators/ci-cd.d.ts +3 -0
- package/dist/evaluators/ci-cd.d.ts.map +1 -0
- package/dist/evaluators/ci-cd.js +155 -0
- package/dist/evaluators/ci-cd.js.map +1 -0
- package/dist/evaluators/configuration-management.d.ts +3 -0
- package/dist/evaluators/configuration-management.d.ts.map +1 -0
- package/dist/evaluators/configuration-management.js +146 -0
- package/dist/evaluators/configuration-management.js.map +1 -0
- package/dist/evaluators/database.d.ts +3 -0
- package/dist/evaluators/database.d.ts.map +1 -0
- package/dist/evaluators/database.js +179 -0
- package/dist/evaluators/database.js.map +1 -0
- package/dist/evaluators/error-handling.d.ts +3 -0
- package/dist/evaluators/error-handling.d.ts.map +1 -0
- package/dist/evaluators/error-handling.js +180 -0
- package/dist/evaluators/error-handling.js.map +1 -0
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +48 -0
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/logging-privacy.d.ts +3 -0
- package/dist/evaluators/logging-privacy.d.ts.map +1 -0
- package/dist/evaluators/logging-privacy.js +147 -0
- package/dist/evaluators/logging-privacy.js.map +1 -0
- package/dist/evaluators/maintainability.d.ts +3 -0
- package/dist/evaluators/maintainability.d.ts.map +1 -0
- package/dist/evaluators/maintainability.js +243 -0
- package/dist/evaluators/maintainability.js.map +1 -0
- package/dist/evaluators/portability.d.ts +3 -0
- package/dist/evaluators/portability.d.ts.map +1 -0
- package/dist/evaluators/portability.js +180 -0
- package/dist/evaluators/portability.js.map +1 -0
- package/dist/evaluators/rate-limiting.d.ts +3 -0
- package/dist/evaluators/rate-limiting.d.ts.map +1 -0
- package/dist/evaluators/rate-limiting.js +161 -0
- package/dist/evaluators/rate-limiting.js.map +1 -0
- package/dist/evaluators/scalability.d.ts.map +1 -1
- package/dist/evaluators/scalability.js +8 -3
- package/dist/evaluators/scalability.js.map +1 -1
- package/dist/evaluators/software-practices.d.ts.map +1 -1
- package/dist/evaluators/software-practices.js +14 -3
- package/dist/evaluators/software-practices.js.map +1 -1
- package/dist/evaluators/testing.d.ts.map +1 -1
- package/dist/evaluators/testing.js +6 -2
- package/dist/evaluators/testing.js.map +1 -1
- package/dist/evaluators/ux.d.ts +3 -0
- package/dist/evaluators/ux.d.ts.map +1 -0
- package/dist/evaluators/ux.js +175 -0
- package/dist/evaluators/ux.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/judges/authentication.d.ts +3 -0
- package/dist/judges/authentication.d.ts.map +1 -0
- package/dist/judges/authentication.js +34 -0
- package/dist/judges/authentication.js.map +1 -0
- package/dist/judges/backwards-compatibility.d.ts +3 -0
- package/dist/judges/backwards-compatibility.d.ts.map +1 -0
- package/dist/judges/backwards-compatibility.js +34 -0
- package/dist/judges/backwards-compatibility.js.map +1 -0
- package/dist/judges/caching.d.ts +3 -0
- package/dist/judges/caching.d.ts.map +1 -0
- package/dist/judges/caching.js +34 -0
- package/dist/judges/caching.js.map +1 -0
- package/dist/judges/ci-cd.d.ts +3 -0
- package/dist/judges/ci-cd.d.ts.map +1 -0
- package/dist/judges/ci-cd.js +34 -0
- package/dist/judges/ci-cd.js.map +1 -0
- package/dist/judges/configuration-management.d.ts +3 -0
- package/dist/judges/configuration-management.d.ts.map +1 -0
- package/dist/judges/configuration-management.js +34 -0
- package/dist/judges/configuration-management.js.map +1 -0
- package/dist/judges/database.d.ts +3 -0
- package/dist/judges/database.d.ts.map +1 -0
- package/dist/judges/database.js +34 -0
- package/dist/judges/database.js.map +1 -0
- package/dist/judges/error-handling.d.ts +3 -0
- package/dist/judges/error-handling.d.ts.map +1 -0
- package/dist/judges/error-handling.js +34 -0
- package/dist/judges/error-handling.js.map +1 -0
- package/dist/judges/index.d.ts.map +1 -1
- package/dist/judges/index.js +24 -0
- package/dist/judges/index.js.map +1 -1
- package/dist/judges/logging-privacy.d.ts +3 -0
- package/dist/judges/logging-privacy.d.ts.map +1 -0
- package/dist/judges/logging-privacy.js +34 -0
- package/dist/judges/logging-privacy.js.map +1 -0
- package/dist/judges/maintainability.d.ts +3 -0
- package/dist/judges/maintainability.d.ts.map +1 -0
- package/dist/judges/maintainability.js +34 -0
- package/dist/judges/maintainability.js.map +1 -0
- package/dist/judges/portability.d.ts +3 -0
- package/dist/judges/portability.d.ts.map +1 -0
- package/dist/judges/portability.js +34 -0
- package/dist/judges/portability.js.map +1 -0
- package/dist/judges/rate-limiting.d.ts +3 -0
- package/dist/judges/rate-limiting.d.ts.map +1 -0
- package/dist/judges/rate-limiting.js +34 -0
- package/dist/judges/rate-limiting.js.map +1 -0
- package/dist/judges/ux.d.ts +3 -0
- package/dist/judges/ux.d.ts.map +1 -0
- package/dist/judges/ux.js +34 -0
- package/dist/judges/ux.js.map +1 -0
- package/package.json +2 -2
- package/server.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portability.js","sourceRoot":"","sources":["../../src/evaluators/portability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiting.d.ts","sourceRoot":"","sources":["../../src/evaluators/rate-limiting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CA0K7E"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeRateLimiting(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "RATE";
|
|
6
|
+
// No rate limiting middleware
|
|
7
|
+
const hasRateLimit = /rate.?limit|throttle|express-rate-limit|koa-ratelimit|bottleneck|p-limit|limiter|quota/gi.test(code);
|
|
8
|
+
const hasServerCode = /app\.(listen|use|get|post|put|delete|patch)|createServer|express\(\)|new\s+Hono/gi.test(code);
|
|
9
|
+
if (hasServerCode && !hasRateLimit && code.split("\n").length > 20) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "high",
|
|
13
|
+
title: "No rate limiting on API endpoints",
|
|
14
|
+
description: "API server has no rate limiting. Any client can make unlimited requests, enabling DDoS attacks, brute-force login attempts, scraping, and resource exhaustion.",
|
|
15
|
+
recommendation: "Add rate limiting middleware (express-rate-limit, koa-ratelimit). Apply per-IP and per-user limits. Set stricter limits on auth endpoints.",
|
|
16
|
+
reference: "OWASP API Security Top 10: API4 — Unrestricted Resource Consumption",
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// No request body size limit
|
|
20
|
+
const hasBodyParser = /bodyParser|express\.json|express\.urlencoded|body-parser|app\.use\s*\(\s*express\.json/gi.test(code);
|
|
21
|
+
const hasBodyLimit = /limit\s*:\s*["'`]\d|maxSize|maxBodySize|maxContentLength|payloadLimit/gi.test(code);
|
|
22
|
+
if (hasBodyParser && !hasBodyLimit) {
|
|
23
|
+
findings.push({
|
|
24
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
25
|
+
severity: "medium",
|
|
26
|
+
title: "Request body parser without size limit",
|
|
27
|
+
description: "Body parser middleware is used without a size limit. Attackers can send arbitrarily large payloads to exhaust server memory.",
|
|
28
|
+
recommendation: "Configure body parser with a size limit: express.json({ limit: '1mb' }). Set limits appropriate for your use case.",
|
|
29
|
+
reference: "Express Security Best Practices / OWASP",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// Unbounded query results
|
|
33
|
+
const unboundedQueryPattern = /db\.find\s*\(\s*(?:\{\s*\}|\))|\.find\s*\(\s*\)/gi;
|
|
34
|
+
const unboundedLines = getLineNumbers(code, unboundedQueryPattern);
|
|
35
|
+
if (unboundedLines.length > 0) {
|
|
36
|
+
findings.push({
|
|
37
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
38
|
+
severity: "medium",
|
|
39
|
+
title: "Unbounded query results without limit",
|
|
40
|
+
description: `Found ${unboundedLines.length} database query/queries without a limit. A single request could return millions of rows, crashing the server.`,
|
|
41
|
+
lineNumbers: unboundedLines,
|
|
42
|
+
recommendation: "Always enforce a maximum result limit: db.find({}).limit(100). Implement pagination and enforce maximum page sizes.",
|
|
43
|
+
reference: "API Rate Limiting / Database Query Safety",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// No rate limit headers in responses
|
|
47
|
+
if (hasServerCode && !hasRateLimit && code.split("\n").length > 40) {
|
|
48
|
+
findings.push({
|
|
49
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
50
|
+
severity: "low",
|
|
51
|
+
title: "No rate limit headers in API responses",
|
|
52
|
+
description: "API responses don't include standard rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After).",
|
|
53
|
+
recommendation: "Return rate limit headers on responses so clients can self-throttle. Include Retry-After on 429 responses.",
|
|
54
|
+
reference: "IETF Rate Limit Headers / RFC 6585",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// External API calls without backoff
|
|
58
|
+
const externalCallPattern = /fetch\s*\(\s*["'`]https?:\/\/|axios\.(?:get|post|put|delete)|http\.(?:get|post)/gi;
|
|
59
|
+
const externalCallLines = getLineNumbers(code, externalCallPattern);
|
|
60
|
+
const hasBackoff = /backoff|retry|exponential|setTimeout.*retry|p-retry|cockatiel|polly/gi.test(code);
|
|
61
|
+
if (externalCallLines.length > 0 && !hasBackoff) {
|
|
62
|
+
findings.push({
|
|
63
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
64
|
+
severity: "medium",
|
|
65
|
+
title: "External API calls without retry/backoff strategy",
|
|
66
|
+
description: `Found ${externalCallLines.length} external API call(s) without visible retry/backoff logic. Failed requests won't be retried, and rapid retries could get your client rate-limited or banned.`,
|
|
67
|
+
lineNumbers: externalCallLines.slice(0, 3),
|
|
68
|
+
recommendation: "Implement exponential backoff with jitter for external API calls. Respect Retry-After headers. Use libraries like p-retry or cockatiel.",
|
|
69
|
+
reference: "Exponential Backoff / Rate Limiting Best Practices",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// setInterval without bounds (potential DoS on resources)
|
|
73
|
+
const setIntervalPattern = /setInterval\s*\(/g;
|
|
74
|
+
const setIntervalLines = getLineNumbers(code, setIntervalPattern);
|
|
75
|
+
if (setIntervalLines.length > 0) {
|
|
76
|
+
findings.push({
|
|
77
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
78
|
+
severity: "low",
|
|
79
|
+
title: "setInterval without rate control",
|
|
80
|
+
description: "setInterval runs indefinitely and could generate excessive load. If the interval function is slow, executions can overlap and compound.",
|
|
81
|
+
lineNumbers: setIntervalLines,
|
|
82
|
+
recommendation: "Use setTimeout with re-scheduling instead of setInterval to prevent overlap. Add guards to skip execution if the previous run hasn't completed.",
|
|
83
|
+
reference: "JavaScript Timer Best Practices",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Auth endpoints without stricter rate limits
|
|
87
|
+
const authRoutePattern = /(?:post|put)\s*\(\s*['"]\/(?:auth|login|signin|register|signup|password|reset|forgot|token|oauth)/gi;
|
|
88
|
+
const authRouteLines = getLineNumbers(code, authRoutePattern);
|
|
89
|
+
const hasRateLimiter = /rateLimit|rateLimiter|rate_limit|throttle/gi.test(code);
|
|
90
|
+
if (authRouteLines.length > 0 && !hasRateLimiter) {
|
|
91
|
+
findings.push({
|
|
92
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
93
|
+
severity: "high",
|
|
94
|
+
title: "Authentication endpoints without rate limiting",
|
|
95
|
+
description: `Found ${authRouteLines.length} authentication endpoint(s) without visible rate limiting. Auth endpoints are prime targets for brute-force and credential-stuffing attacks.`,
|
|
96
|
+
lineNumbers: authRouteLines,
|
|
97
|
+
recommendation: "Apply strict rate limits to auth endpoints (e.g., 5-10 requests/minute per IP). Use progressive delays or CAPTCHA after failed attempts. Consider using 'express-rate-limit' or 'rate-limiter-flexible'.",
|
|
98
|
+
reference: "OWASP: Brute Force Protection / NIST 800-63B",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// File upload without size limit
|
|
102
|
+
const uploadPattern = /multer\s*\(|upload\s*\.\s*(?:single|array|fields)|formidable|busboy|multipart/gi;
|
|
103
|
+
const uploadLines = getLineNumbers(code, uploadPattern);
|
|
104
|
+
const hasUploadLimit = /limits\s*:\s*\{|maxFileSize|fileSizeLimit|maxFiles/gi.test(code);
|
|
105
|
+
if (uploadLines.length > 0 && !hasUploadLimit) {
|
|
106
|
+
findings.push({
|
|
107
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
108
|
+
severity: "high",
|
|
109
|
+
title: "File upload without size or count limits",
|
|
110
|
+
description: `Found ${uploadLines.length} file upload handler(s) without visible size limits. Unbounded uploads can exhaust disk space and memory, causing denial of service.`,
|
|
111
|
+
lineNumbers: uploadLines,
|
|
112
|
+
recommendation: "Set explicit file size limits (e.g., multer({ limits: { fileSize: 5 * 1024 * 1024 } })). Limit the number of files per request. Validate file types.",
|
|
113
|
+
reference: "OWASP: Unrestricted File Upload / Multer Limits",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Missing 429 status code responses
|
|
117
|
+
const has429 = /429|Too Many Requests|too_many_requests|RATE_LIMIT|rateLimited/gi.test(code);
|
|
118
|
+
const hasApiEndpoints = /app\.\s*(?:get|post|put|delete|patch)\s*\(|router\.\s*(?:get|post|put|delete|patch)\s*\(/gi.test(code);
|
|
119
|
+
if (hasApiEndpoints && !has429 && !hasRateLimiter) {
|
|
120
|
+
findings.push({
|
|
121
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
122
|
+
severity: "medium",
|
|
123
|
+
title: "API endpoints with no 429 (Too Many Requests) handling",
|
|
124
|
+
description: "API endpoints found but no 429 status code or rate limiting middleware detected. Without rate limiting responses, clients have no feedback mechanism to back off.",
|
|
125
|
+
recommendation: "Return 429 status with Retry-After header when rate limits are exceeded. Include rate limit headers (X-RateLimit-Remaining, X-RateLimit-Reset) in all responses.",
|
|
126
|
+
reference: "RFC 6585: 429 Too Many Requests / IETF Rate Limiting Headers",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// WebSocket connections without limits
|
|
130
|
+
const wsPattern = /new\s+WebSocket(?:Server)?|wss?\.\s*on\s*\(\s*['"]connection/gi;
|
|
131
|
+
const wsLines = getLineNumbers(code, wsPattern);
|
|
132
|
+
const hasWsLimit = /maxPayload|maxConnections|maxClientsCount|perMessageDeflate.*threshold/gi.test(code);
|
|
133
|
+
if (wsLines.length > 0 && !hasWsLimit) {
|
|
134
|
+
findings.push({
|
|
135
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
136
|
+
severity: "high",
|
|
137
|
+
title: "WebSocket server without connection or message limits",
|
|
138
|
+
description: `Found ${wsLines.length} WebSocket server setup(s) without visible connection or payload limits. Unbounded WebSocket connections can exhaust server resources.`,
|
|
139
|
+
lineNumbers: wsLines,
|
|
140
|
+
recommendation: "Set maxPayload to limit message sizes. Limit concurrent connections per client. Implement message rate limiting per connection. Set idle timeouts.",
|
|
141
|
+
reference: "ws Package: Connection Limits / WebSocket Security",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Recursive/infinite retry without backoff
|
|
145
|
+
const retryPattern = /retry|retryCount|maxRetries|attempts?\s*[<>]/gi;
|
|
146
|
+
const retryLines = getLineNumbers(code, retryPattern);
|
|
147
|
+
const hasBackoffStrategy = /backoff|exponential|delay\s*\*|Math\.pow|jitter/gi.test(code);
|
|
148
|
+
if (retryLines.length > 0 && !hasBackoffStrategy) {
|
|
149
|
+
findings.push({
|
|
150
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
151
|
+
severity: "medium",
|
|
152
|
+
title: "Retry logic without exponential backoff",
|
|
153
|
+
description: `Found ${retryLines.length} retry reference(s) without backoff or delay escalation. Retrying at a fixed rate can overwhelm downstream services and cause cascading failures.`,
|
|
154
|
+
lineNumbers: retryLines,
|
|
155
|
+
recommendation: "Use exponential backoff with jitter: delay = baseDelay * Math.pow(2, attempt) + randomJitter. Set a maximum retry count. Use libraries like 'p-retry' or 'axios-retry'.",
|
|
156
|
+
reference: "AWS Architecture Blog: Exponential Backoff and Jitter",
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return findings;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=rate-limiting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiting.js","sourceRoot":"","sources":["../../src/evaluators/rate-limiting.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scalability.d.ts","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scalability.d.ts","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CA0L5E"}
|
|
@@ -60,14 +60,19 @@ export function analyzeScalability(code, language) {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
// Single-threaded heavy computation
|
|
63
|
+
// Detect nested loops, known CPU-intensive operations, and blocking patterns
|
|
63
64
|
const heavyCompPattern = /(?:for|while)\s*\(.*(?:length|size|count).*\)[\s\S]{0,200}(?:for|while)\s*\(/gi;
|
|
64
|
-
|
|
65
|
+
const cpuIntensiveOps = /crypto\.pbkdf2Sync|crypto\.scryptSync|bcrypt\.hashSync|JSON\.parse\s*\(\s*JSON\.stringify|structuredClone|zlib\.[^a-z]*Sync|(?:sort|reduce|map|filter)\s*\([^)]*(?:sort|reduce|map|filter)\s*\(/gi;
|
|
66
|
+
const hasNestedLoops = heavyCompPattern.test(code);
|
|
67
|
+
const cpuOpsLines = getLineNumbers(code, cpuIntensiveOps);
|
|
68
|
+
if (hasNestedLoops || cpuOpsLines.length > 0) {
|
|
65
69
|
findings.push({
|
|
66
70
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
67
71
|
severity: "low",
|
|
68
72
|
title: "CPU-intensive computation may block scaling",
|
|
69
|
-
description: "
|
|
70
|
-
|
|
73
|
+
description: `Detected ${hasNestedLoops ? "nested loops" : ""}${hasNestedLoops && cpuOpsLines.length > 0 ? " and " : ""}${cpuOpsLines.length > 0 ? `${cpuOpsLines.length} synchronous/heavy operation(s)` : ""}. Heavy computation on the main thread blocks the event loop (Node.js) or consumes thread pool capacity.`,
|
|
74
|
+
lineNumbers: cpuOpsLines.length > 0 ? cpuOpsLines : undefined,
|
|
75
|
+
recommendation: "Offload CPU-intensive work to worker threads, a job queue (Bull, Celery), or a dedicated compute service. Use async variants of crypto operations (pbkdf2, scrypt). Consider WebAssembly for hot-path computation.",
|
|
71
76
|
reference: "Node.js Worker Threads / Job Queue Patterns",
|
|
72
77
|
});
|
|
73
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scalability.js","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,QAAgB;IAC/D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC;IAEvB,uBAAuB;IACvB,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,EAAE,0CAA0C,CAAC,CAAC;IAC1F,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,+BAA+B;YACtC,WAAW,EAAE,6JAA6J;YAC1K,WAAW,EAAE,gBAAgB;YAC7B,cAAc,EAAE,sJAAsJ;YACtK,SAAS,EAAE,sCAAsC;SAClD,CAAC,CAAC;IACL,CAAC;IAED,0BAA0B;IAC1B,MAAM,YAAY,GAAG,kKAAkK,CAAC;IACxL,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,oCAAoC;YAC3C,WAAW,EAAE,8JAA8J;YAC3K,WAAW,EAAE,UAAU;YACvB,cAAc,EAAE,kGAAkG;YAClH,SAAS,EAAE,oCAAoC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,qDAAqD;IACrD,MAAM,eAAe,GAAG,kHAAkH,CAAC;IAC3I,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,gCAAgC;YACvC,WAAW,EAAE,oJAAoJ;YACjK,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,uHAAuH;YACvI,SAAS,EAAE,+CAA+C;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,+BAA+B;IAC/B,MAAM,YAAY,GAAG,8HAA8H,CAAC;IACpJ,MAAM,UAAU,GAAG,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,gCAAgC;YACvC,WAAW,EAAE,yJAAyJ;YACtK,WAAW,EAAE,UAAU;YACvB,cAAc,EAAE,2KAA2K;YAC3L,SAAS,EAAE,kCAAkC;SAC9C,CAAC,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,MAAM,gBAAgB,GAAG,gFAAgF,CAAC;IAC1G,
|
|
1
|
+
{"version":3,"file":"scalability.js","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"software-practices.d.ts","sourceRoot":"","sources":["../../src/evaluators/software-practices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"software-practices.d.ts","sourceRoot":"","sources":["../../src/evaluators/software-practices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAySlF"}
|
|
@@ -32,8 +32,14 @@ export function analyzeSoftwarePractices(code, language) {
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
// Magic numbers
|
|
35
|
+
const codeLines = code.split("\n");
|
|
35
36
|
const magicNumberPattern = /(?:===?|!==?|<=?|>=?|&&|\|\|)\s*\d{2,}|(?:timeout|delay|limit|max|min|size|count|length|port|interval)\s*[:=]\s*\d{3,}/gi;
|
|
36
|
-
|
|
37
|
+
// Filter out common well-known numbers (HTTP status codes, ports, permissions, etc.)
|
|
38
|
+
const wellKnownNumbers = /\b(?:200|201|204|301|302|304|400|401|403|404|405|409|422|429|500|502|503|504|80|443|8080|3000|8443|3001|5432|27017|6379|0o?[0-7]{3,4}|0x[0-9a-f]+|1000|1024|255|256|65535|1e[3-9])\b/gi;
|
|
39
|
+
const magicLines = getLineNumbers(code, magicNumberPattern).filter(lineNum => {
|
|
40
|
+
const line = codeLines[lineNum - 1] || "";
|
|
41
|
+
return !wellKnownNumbers.test(line);
|
|
42
|
+
});
|
|
37
43
|
if (magicLines.length > 0) {
|
|
38
44
|
findings.push({
|
|
39
45
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -46,7 +52,6 @@ export function analyzeSoftwarePractices(code, language) {
|
|
|
46
52
|
});
|
|
47
53
|
}
|
|
48
54
|
// Very long functions (>50 lines)
|
|
49
|
-
const codeLines = code.split("\n");
|
|
50
55
|
let funcStart = -1;
|
|
51
56
|
let braceDepth = 0;
|
|
52
57
|
const longFunctions = [];
|
|
@@ -192,7 +197,13 @@ export function analyzeSoftwarePractices(code, language) {
|
|
|
192
197
|
});
|
|
193
198
|
}
|
|
194
199
|
// Type coercion risks (JavaScript ==)
|
|
195
|
-
|
|
200
|
+
// More precise pattern: match == but exclude ===, !==, ==>, arrow functions, and template literals
|
|
201
|
+
const looseEqualPattern = /(?<![!=<>])\s==\s(?!=)/g;
|
|
202
|
+
const looseEqualLines = getLineNumbers(code, looseEqualPattern).filter(lineNum => {
|
|
203
|
+
const line = codeLines[lineNum - 1] || "";
|
|
204
|
+
// Exclude lines that are comments, strings with CSS selectors, or template literals
|
|
205
|
+
return !(/^\s*(?:\/\/|\*|\/\*)/.test(line)) && !(/['"].*==.*['"]/.test(line));
|
|
206
|
+
});
|
|
196
207
|
if (looseEqualLines.length > 0 && (language === "javascript" || language === "typescript" || language === "jsx" || language === "tsx")) {
|
|
197
208
|
findings.push({
|
|
198
209
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"software-practices.js","sourceRoot":"","sources":["../../src/evaluators/software-practices.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,QAAgB;IACrE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC;IAEvB,8BAA8B;IAC9B,MAAM,cAAc,GAAG,8BAA8B,CAAC;IACtD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,6BAA6B;YACpC,WAAW,EAAE,4HAA4H;YACzI,WAAW,EAAE,QAAQ;YACrB,cAAc,EAAE,gJAAgJ;YAChK,SAAS,EAAE,wCAAwC;SACpD,CAAC,CAAC;IACL,CAAC;IAED,mBAAmB;IACnB,MAAM,eAAe,GAAG,0BAA0B,CAAC;IACnD,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,8BAA8B;YACrC,WAAW,EAAE,4GAA4G;YACzH,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,iJAAiJ;YACjK,SAAS,EAAE,uCAAuC;SACnD,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,MAAM,kBAAkB,GAAG,0HAA0H,CAAC;IACtJ,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"software-practices.js","sourceRoot":"","sources":["../../src/evaluators/software-practices.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,QAAgB;IACrE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC;IAEvB,8BAA8B;IAC9B,MAAM,cAAc,GAAG,8BAA8B,CAAC;IACtD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,6BAA6B;YACpC,WAAW,EAAE,4HAA4H;YACzI,WAAW,EAAE,QAAQ;YACrB,cAAc,EAAE,gJAAgJ;YAChK,SAAS,EAAE,wCAAwC;SACpD,CAAC,CAAC;IACL,CAAC;IAED,mBAAmB;IACnB,MAAM,eAAe,GAAG,0BAA0B,CAAC;IACnD,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,8BAA8B;YACrC,WAAW,EAAE,4GAA4G;YACzH,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,iJAAiJ;YACjK,SAAS,EAAE,uCAAuC;SACnD,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,kBAAkB,GAAG,0HAA0H,CAAC;IACtJ,qFAAqF;IACrF,MAAM,gBAAgB,GAAG,wLAAwL,CAAC;IAClN,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QAC3E,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,wBAAwB;YAC/B,WAAW,EAAE,6HAA6H;YAC1I,WAAW,EAAE,UAAU;YACvB,cAAc,EAAE,oIAAoI;YACpJ,SAAS,EAAE,4CAA4C;SACxD,CAAC,CAAC;IACL,CAAC;IAED,kCAAkC;IAClC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,oGAAoG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5H,IAAI,UAAU,KAAK,CAAC;gBAAE,SAAS,GAAG,CAAC,CAAC;QACtC,CAAC;QACD,UAAU,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACvD,UAAU,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACvD,IAAI,UAAU,KAAK,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,GAAG,SAAS,GAAG,EAAE,EAAE,CAAC;gBACvB,aAAa,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;YACpC,CAAC;YACD,SAAS,GAAG,CAAC,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,oCAAoC;YAC3C,WAAW,EAAE,4KAA4K;YACzL,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,iHAAiH;YACjI,SAAS,EAAE,8CAA8C;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B;IAC3B,MAAM,WAAW,GAAG,oDAAoD,CAAC;IACzE,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,gCAAgC;YACvC,WAAW,EAAE,0IAA0I;YACvJ,WAAW,EAAE,SAAS;YACtB,cAAc,EAAE,wJAAwJ;YACxK,SAAS,EAAE,qCAAqC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,qBAAqB;IACrB,MAAM,iBAAiB,GAAG,+BAA+B,CAAC;IAC1D,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAChE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,+CAA+C;YACtD,WAAW,EAAE,4HAA4H;YACzI,WAAW,EAAE,eAAe;YAC5B,cAAc,EAAE,8IAA8I;YAC9J,SAAS,EAAE,uCAAuC;SACnD,CAAC,CAAC;IACL,CAAC;IAED,sBAAsB;IACtB,MAAM,aAAa,GAAG,4FAA4F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9H,MAAM,YAAY,GAAG,6EAA6E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9G,IAAI,YAAY,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,8BAA8B;YACrC,WAAW,EAAE,6KAA6K;YAC1L,cAAc,EAAE,mKAAmK;YACnL,SAAS,EAAE,2CAA2C;SACvD,CAAC,CAAC;IACL,CAAC;IAED,yCAAyC;IACzC,MAAM,eAAe,GAAG,sEAAsE,CAAC;IAC/F,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,2CAA2C;YAClD,WAAW,EAAE,mIAAmI;YAChJ,WAAW,EAAE,UAAU;YACvB,cAAc,EAAE,mHAAmH;YACnI,SAAS,EAAE,4BAA4B;SACxC,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B;IAC3B,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,aAAa,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3E,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC,CAAC;IACH,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,gCAAgC;YACvC,WAAW,EAAE,kIAAkI;YAC/I,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,cAAc,EAAE,4HAA4H;YAC5I,SAAS,EAAE,iDAAiD;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,MAAM,UAAU,GAAG,gBAAgB,CAAC;IACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,KAAK,CAAC,EAAE,CAAC;QAChI,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,yCAAyC;YAChD,WAAW,EAAE,qJAAqJ;YAClK,WAAW,EAAE,QAAQ;YACrB,cAAc,EAAE,+EAA+E;YAC/F,SAAS,EAAE,qBAAqB;SACjC,CAAC,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,MAAM,qBAAqB,GAAG,wDAAwD,CAAC;IACvF,MAAM,mBAAmB,GAAG,cAAc,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IACxE,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,gDAAgD;YACvD,WAAW,EAAE,4HAA4H;YACzI,WAAW,EAAE,mBAAmB;YAChC,cAAc,EAAE,iHAAiH;YACjI,SAAS,EAAE,mDAAmD;SAC/D,CAAC,CAAC;IACL,CAAC;IAED,0CAA0C;IAC1C,MAAM,iBAAiB,GAAG,yCAAyC,CAAC;IACpE,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAChE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,mCAAmC;YAC1C,WAAW,EAAE,sIAAsI;YACnJ,WAAW,EAAE,eAAe;YAC5B,cAAc,EAAE,+IAA+I;YAC/J,SAAS,EAAE,mCAAmC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,mGAAmG;IACnG,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;IACpD,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QAC/E,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,oFAAoF;QACpF,OAAO,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IACH,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,KAAK,CAAC,EAAE,CAAC;QACvI,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,6CAA6C;YACpD,WAAW,EAAE,qJAAqJ;YAClK,WAAW,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACxC,cAAc,EAAE,mEAAmE;YACnF,SAAS,EAAE,gCAAgC;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC/D,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC/E,IAAI,SAAS,CAAC,MAAM,GAAG,GAAG,IAAI,aAAa,GAAG,EAAE,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,4DAA4D;YACnE,WAAW,EAAE,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,qEAAqE;YACzI,cAAc,EAAE,2HAA2H;YAC3I,SAAS,EAAE,0CAA0C;SACtD,CAAC,CAAC;IACL,CAAC;IAED,0CAA0C;IAC1C,MAAM,iBAAiB,GAAa,EAAE,CAAC;IACvC,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5B,IAAI,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjF,MAAM,eAAe,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YAC/E,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;gBACzB,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,4CAA4C;YACnD,WAAW,EAAE,gGAAgG;YAC7G,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1C,cAAc,EAAE,2FAA2F;YAC3G,SAAS,EAAE,gCAAgC;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,uBAAuB;IACvB,MAAM,eAAe,GAAG,6DAA6D,CAAC;IACtF,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,4CAA4C;YACnD,WAAW,EAAE,+DAA+D;YAC5E,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,+FAA+F;YAC/G,SAAS,EAAE,sCAAsC;SAClD,CAAC,CAAC;IACL,CAAC;IAED,+BAA+B;IAC/B,MAAM,gBAAgB,GAAG,uEAAuE,CAAC;IACjG,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC9D,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,8CAA8C;YACrD,WAAW,EAAE,mHAAmH;YAChI,WAAW,EAAE,cAAc;YAC3B,cAAc,EAAE,sHAAsH;YACtI,SAAS,EAAE,iCAAiC;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/evaluators/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/evaluators/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAsMxE"}
|
|
@@ -167,14 +167,18 @@ export function analyzeTesting(code, language) {
|
|
|
167
167
|
}
|
|
168
168
|
else {
|
|
169
169
|
// No test structure detected - check if this is production code without tests
|
|
170
|
+
// Exclude config files, type definitions, constants, and utility barrel files
|
|
170
171
|
const hasFunctions = /function\s+\w+|=>\s*\{|def\s+\w+|public\s+\w+\s+\w+\s*\(/i.test(code);
|
|
171
172
|
const isLargeFile = lines.length > 50;
|
|
172
|
-
|
|
173
|
+
const isConfigOrUtility = /(?:config|configuration|settings|constants|types|interfaces|models|schema|migration|seed|fixture|mock|stub|setup|index|barrel)\b/gi.test(code);
|
|
174
|
+
const isTypeDefinitionFile = /^(?:export\s+)?(?:type|interface|enum|declare)\s+/gim.test(code) && !(/(function|class)\s+\w+.*\{[\s\S]{10,}\}/gi.test(code));
|
|
175
|
+
const hasMinimalLogic = (code.match(/(?:if|for|while|switch)\s*\(/g) || []).length >= 3;
|
|
176
|
+
if (hasFunctions && isLargeFile && hasMinimalLogic && !isConfigOrUtility && !isTypeDefinitionFile) {
|
|
173
177
|
findings.push({
|
|
174
178
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
175
179
|
severity: "medium",
|
|
176
180
|
title: "No tests detected for production code",
|
|
177
|
-
description: "This file contains significant logic but no accompanying tests were detected.",
|
|
181
|
+
description: "This file contains significant logic (multiple branches/loops) but no accompanying tests were detected.",
|
|
178
182
|
recommendation: "Write unit tests covering the main functions, edge cases, and error paths. Aim for meaningful coverage of critical paths.",
|
|
179
183
|
reference: "Test-Driven Development / Testing Pyramid",
|
|
180
184
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/evaluators/testing.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/evaluators/testing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ux.d.ts","sourceRoot":"","sources":["../../src/evaluators/ux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAyLnE"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeUx(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "UX";
|
|
6
|
+
// Inline event handlers (onClick, onSubmit in HTML)
|
|
7
|
+
const inlineHandlerPattern = /\bon[A-Z]\w+\s*=\s*["'`]/gi;
|
|
8
|
+
const inlineHandlerLines = getLineNumbers(code, inlineHandlerPattern);
|
|
9
|
+
if (inlineHandlerLines.length > 0) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "low",
|
|
13
|
+
title: "Inline event handlers in HTML",
|
|
14
|
+
description: `Found ${inlineHandlerLines.length} inline event handler(s). Inline handlers mix behavior with markup, break CSP policies, and are harder to maintain.`,
|
|
15
|
+
lineNumbers: inlineHandlerLines,
|
|
16
|
+
recommendation: "Use addEventListener() or framework event bindings (React onClick, Vue @click). Separate behavior from markup for maintainability and CSP compliance.",
|
|
17
|
+
reference: "MDN: Inline Event Handlers / Content Security Policy",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// No loading/disabled state for forms
|
|
21
|
+
const hasForm = /form|submit|<button|<input.*type=["']submit/gi.test(code);
|
|
22
|
+
const hasLoadingState = /loading|isLoading|submitting|isSubmitting|disabled|pending|spinner|skeleton/gi.test(code);
|
|
23
|
+
if (hasForm && !hasLoadingState && code.split("\n").length > 15) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
26
|
+
severity: "medium",
|
|
27
|
+
title: "Form submission without loading/disabled state",
|
|
28
|
+
description: "Forms are submitted without visible loading state or button disabling. Users may click multiple times causing duplicate submissions.",
|
|
29
|
+
recommendation: "Disable the submit button during submission. Show a loading indicator. Prevent double-submission at the application layer.",
|
|
30
|
+
reference: "Nielsen's Heuristic #1: Visibility of System Status",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// Generic error messages in UI
|
|
34
|
+
const genericUiErrorPattern = /["'`](?:Error|Something went wrong|An error occurred|Oops|Server error)["'`]/gi;
|
|
35
|
+
const genericUiErrorLines = getLineNumbers(code, genericUiErrorPattern);
|
|
36
|
+
if (genericUiErrorLines.length > 0) {
|
|
37
|
+
findings.push({
|
|
38
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
39
|
+
severity: "low",
|
|
40
|
+
title: "Generic error messages shown to users",
|
|
41
|
+
description: `Found ${genericUiErrorLines.length} generic error message(s). Users need specific, actionable error messages to understand what happened and what to do.`,
|
|
42
|
+
lineNumbers: genericUiErrorLines,
|
|
43
|
+
recommendation: "Provide specific error messages explaining what went wrong and what the user can do ('Please check your internet connection and try again' vs 'Something went wrong').",
|
|
44
|
+
reference: "Nielsen's Heuristic #9: Help Users Recognize Errors",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Raw JSON/data dump in responses
|
|
48
|
+
const rawJsonDump = /res\.json\s*\(\s*(?:data|results|rows|records|items)\s*\)/gi;
|
|
49
|
+
const rawDumpLines = getLineNumbers(code, rawJsonDump);
|
|
50
|
+
if (rawDumpLines.length > 0) {
|
|
51
|
+
findings.push({
|
|
52
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
53
|
+
severity: "info",
|
|
54
|
+
title: "Raw data returned without formatting envelope",
|
|
55
|
+
description: "Data is returned directly without a response envelope (pagination info, total count, metadata). This makes it harder for UIs to display data properly.",
|
|
56
|
+
lineNumbers: rawDumpLines,
|
|
57
|
+
recommendation: "Wrap responses in an envelope: { data: [...], meta: { total, page, limit }, links: { next, prev } }. This enables pagination UI and data status indicators.",
|
|
58
|
+
reference: "JSON:API / REST API Design Guidelines",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// No placeholder/label on inputs
|
|
62
|
+
const inputNoLabelPattern = /<input[^>]*(?!.*(?:aria-label|placeholder|id=))[^>]*>/gi;
|
|
63
|
+
const inputLines = getLineNumbers(code, /<input\b/gi);
|
|
64
|
+
const hasLabels = /<label|aria-label|placeholder/gi.test(code);
|
|
65
|
+
if (inputLines.length > 0 && !hasLabels) {
|
|
66
|
+
findings.push({
|
|
67
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
68
|
+
severity: "medium",
|
|
69
|
+
title: "Form inputs without labels or placeholders",
|
|
70
|
+
description: "Input elements found without associated labels or placeholders. Users won't know what to enter in these fields.",
|
|
71
|
+
lineNumbers: inputLines,
|
|
72
|
+
recommendation: "Use <label for='inputId'> for every input. Add placeholder text for additional guidance. Both improve UX and accessibility.",
|
|
73
|
+
reference: "WCAG 1.3.1: Info and Relationships",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Confirmation for destructive actions
|
|
77
|
+
const destructivePattern = /delete|remove|destroy|drop|purge|erase/gi;
|
|
78
|
+
const hasConfirmation = /confirm|modal|dialog|are you sure|confirmation/gi.test(code);
|
|
79
|
+
const hasDestructiveEndpoint = /app\.(delete|post)\s*\([^)]*(?:delete|remove|destroy)/gi.test(code);
|
|
80
|
+
if (hasDestructiveEndpoint && !hasConfirmation) {
|
|
81
|
+
findings.push({
|
|
82
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
83
|
+
severity: "low",
|
|
84
|
+
title: "Destructive actions without confirmation",
|
|
85
|
+
description: "Destructive operations (delete, remove) are handled without confirmation prompts. Users could accidentally destroy data.",
|
|
86
|
+
recommendation: "Add confirmation dialogs for destructive actions. Show what will be affected. Consider soft-delete with undo capability.",
|
|
87
|
+
reference: "Nielsen's Heuristic #5: Error Prevention",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// No pagination
|
|
91
|
+
const hasListEndpoint = /app\.get\s*\([^)]*(?:list|all|users|items|posts|products|orders)/gi.test(code);
|
|
92
|
+
const hasPagination = /page|limit|offset|cursor|skip|take|per_?page|pageSize/gi.test(code);
|
|
93
|
+
const hasDbFind = /db\.find\s*\(\s*(?:\{\s*\}|\))/gi.test(code);
|
|
94
|
+
if ((hasListEndpoint || hasDbFind) && !hasPagination) {
|
|
95
|
+
findings.push({
|
|
96
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
97
|
+
severity: "medium",
|
|
98
|
+
title: "List endpoints without pagination",
|
|
99
|
+
description: "Data retrieval endpoints return all results without pagination. This causes slow responses, high memory usage, and poor UX with large datasets.",
|
|
100
|
+
recommendation: "Implement pagination (offset-based or cursor-based). Return total count and page info. Enforce maximum page sizes.",
|
|
101
|
+
reference: "REST API Pagination Best Practices",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// No empty state handling
|
|
105
|
+
const hasEmptyCheck = /(?:\.length\s*===?\s*0|isEmpty|no\s*(?:results|data|items)|empty.?state|emptyState|NoData|NoResults)/gi.test(code);
|
|
106
|
+
const hasListRendering = /\.map\s*\(|\.forEach\s*\(|v-for|ngFor|\*ngFor|\.render\s*\(/gi.test(code);
|
|
107
|
+
if (hasListRendering && !hasEmptyCheck && code.split("\n").length > 30) {
|
|
108
|
+
findings.push({
|
|
109
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
110
|
+
severity: "low",
|
|
111
|
+
title: "List rendering without empty state handling",
|
|
112
|
+
description: "Code renders lists/collections without checking for empty state. Users see a blank screen with no feedback when no data exists.",
|
|
113
|
+
recommendation: "Always handle the empty state: show a helpful message, illustration, or call-to-action. Check array.length before rendering lists.",
|
|
114
|
+
reference: "UX Design: Empty State Patterns",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Missing success feedback
|
|
118
|
+
const hasMutation = /\.post\s*\(|\.put\s*\(|\.delete\s*\(|\.patch\s*\(|fetch\s*\([^)]*(?:POST|PUT|DELETE|PATCH)/gi.test(code);
|
|
119
|
+
const hasSuccessFeedback = /toast|snackbar|notification|alert\s*\(\s*['"].*(?:success|saved|created|updated|deleted)|showMessage|showSuccess|feedback/gi.test(code);
|
|
120
|
+
if (hasMutation && !hasSuccessFeedback && code.split("\n").length > 30) {
|
|
121
|
+
findings.push({
|
|
122
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
123
|
+
severity: "low",
|
|
124
|
+
title: "Mutations without success feedback",
|
|
125
|
+
description: "POST/PUT/DELETE operations found without visible success feedback. Users don't know if their action worked, leading to repeated submissions.",
|
|
126
|
+
recommendation: "Show success notifications (toasts, alerts) after mutations. Provide clear visual feedback. Consider optimistic UI updates with rollback on failure.",
|
|
127
|
+
reference: "Nielsen's Heuristic #1: Visibility of System Status",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// No progress indicator for long operations
|
|
131
|
+
const hasAsyncOp = /async\s+function|await\s+fetch|\.then\s*\(|Promise\./gi.test(code);
|
|
132
|
+
const hasProgress = /progress|spinner|loading|isLoading|setLoading|skeleton|placeholder/gi.test(code);
|
|
133
|
+
const hasFileProcessing = /readFile|writeFile|stream|pipe\s*\(|transform/gi.test(code);
|
|
134
|
+
if (hasFileProcessing && hasAsyncOp && !hasProgress) {
|
|
135
|
+
findings.push({
|
|
136
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
137
|
+
severity: "low",
|
|
138
|
+
title: "File/stream operations without progress indicators",
|
|
139
|
+
description: "File processing or streaming operations found without progress feedback. Users waiting on long operations without feedback may assume the app is frozen.",
|
|
140
|
+
recommendation: "Show progress bars for file operations. Use streaming progress events. Provide estimated time remaining for large operations.",
|
|
141
|
+
reference: "UX: Progress Indicator Patterns / Nielsen's Heuristic #1",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Hardcoded UI strings (i18n issue from UX perspective)
|
|
145
|
+
const hardcodedStringPattern = /(?:innerHTML|textContent|innerText|placeholder|title|label)\s*=\s*['"][A-Z][a-z]+(?:\s+[a-z]+){2,}['"]/g;
|
|
146
|
+
const hardcodedStringLines = getLineNumbers(code, hardcodedStringPattern);
|
|
147
|
+
if (hardcodedStringLines.length > 3) {
|
|
148
|
+
findings.push({
|
|
149
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
150
|
+
severity: "info",
|
|
151
|
+
title: "Multiple hardcoded UI strings detected",
|
|
152
|
+
description: `Found ${hardcodedStringLines.length} hardcoded UI string(s) directly assigned to DOM properties. This makes copy changes difficult and blocks localization.`,
|
|
153
|
+
lineNumbers: hardcodedStringLines,
|
|
154
|
+
recommendation: "Extract UI strings to a constants file or i18n library. Use translation keys instead of hardcoded strings. This enables copy editing without code changes.",
|
|
155
|
+
reference: "i18n Best Practices / Content Management",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// Form submission without validation
|
|
159
|
+
const formPattern = /onSubmit|handleSubmit|form\.submit|\.submit\s*\(/gi;
|
|
160
|
+
const formLines = getLineNumbers(code, formPattern);
|
|
161
|
+
const hasValidation = /validate|validator|yup|zod|joi|schema|required|minLength|maxLength|pattern\s*=/gi.test(code);
|
|
162
|
+
if (formLines.length > 0 && !hasValidation) {
|
|
163
|
+
findings.push({
|
|
164
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
165
|
+
severity: "medium",
|
|
166
|
+
title: "Form submission without client-side validation",
|
|
167
|
+
description: `Found ${formLines.length} form submission handler(s) without visible validation. Submitting invalid data wastes round trips and frustrates users with server-side error messages.`,
|
|
168
|
+
lineNumbers: formLines,
|
|
169
|
+
recommendation: "Add client-side validation before submission. Use schema validation libraries (Zod, Yup, Joi). Show inline validation feedback. Keep server-side validation as well.",
|
|
170
|
+
reference: "UX: Form Validation Patterns / Nielsen's Heuristic #9: Error Recovery",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return findings;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=ux.js.map
|