@kevinrabun/judges 3.18.3 → 3.19.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 +31 -0
- package/dist/evaluators/accessibility.js +5 -5
- package/dist/evaluators/accessibility.js.map +1 -1
- package/dist/evaluators/ai-code-safety.d.ts.map +1 -1
- package/dist/evaluators/ai-code-safety.js +9 -9
- package/dist/evaluators/ai-code-safety.js.map +1 -1
- package/dist/evaluators/api-design.js +7 -7
- package/dist/evaluators/api-design.js.map +1 -1
- package/dist/evaluators/authentication.d.ts.map +1 -1
- package/dist/evaluators/authentication.js +16 -16
- package/dist/evaluators/authentication.js.map +1 -1
- package/dist/evaluators/backwards-compatibility.js +5 -5
- package/dist/evaluators/backwards-compatibility.js.map +1 -1
- package/dist/evaluators/caching.d.ts.map +1 -1
- package/dist/evaluators/caching.js +7 -7
- package/dist/evaluators/caching.js.map +1 -1
- package/dist/evaluators/ci-cd.d.ts.map +1 -1
- package/dist/evaluators/ci-cd.js +22 -17
- package/dist/evaluators/ci-cd.js.map +1 -1
- package/dist/evaluators/cloud-readiness.d.ts.map +1 -1
- package/dist/evaluators/cloud-readiness.js +6 -6
- package/dist/evaluators/cloud-readiness.js.map +1 -1
- package/dist/evaluators/compliance.d.ts.map +1 -1
- package/dist/evaluators/compliance.js +5 -5
- package/dist/evaluators/compliance.js.map +1 -1
- package/dist/evaluators/concurrency.js +2 -2
- package/dist/evaluators/concurrency.js.map +1 -1
- package/dist/evaluators/configuration-management.d.ts.map +1 -1
- package/dist/evaluators/configuration-management.js +8 -8
- package/dist/evaluators/configuration-management.js.map +1 -1
- package/dist/evaluators/cost-effectiveness.d.ts.map +1 -1
- package/dist/evaluators/cost-effectiveness.js +3 -3
- package/dist/evaluators/cost-effectiveness.js.map +1 -1
- package/dist/evaluators/cybersecurity.d.ts.map +1 -1
- package/dist/evaluators/cybersecurity.js +8 -8
- package/dist/evaluators/cybersecurity.js.map +1 -1
- package/dist/evaluators/data-security.d.ts.map +1 -1
- package/dist/evaluators/data-security.js +11 -11
- package/dist/evaluators/data-security.js.map +1 -1
- package/dist/evaluators/data-sovereignty.d.ts.map +1 -1
- package/dist/evaluators/data-sovereignty.js +10 -10
- package/dist/evaluators/data-sovereignty.js.map +1 -1
- package/dist/evaluators/database.js +7 -7
- package/dist/evaluators/database.js.map +1 -1
- package/dist/evaluators/dependency-health.js +2 -2
- package/dist/evaluators/dependency-health.js.map +1 -1
- package/dist/evaluators/error-handling.d.ts.map +1 -1
- package/dist/evaluators/error-handling.js +10 -10
- package/dist/evaluators/error-handling.js.map +1 -1
- package/dist/evaluators/framework-safety.d.ts.map +1 -1
- package/dist/evaluators/framework-safety.js +10 -10
- package/dist/evaluators/framework-safety.js.map +1 -1
- package/dist/evaluators/iac-security.js +6 -6
- package/dist/evaluators/iac-security.js.map +1 -1
- package/dist/evaluators/internationalization.js +3 -3
- package/dist/evaluators/internationalization.js.map +1 -1
- package/dist/evaluators/logging-privacy.js +2 -2
- package/dist/evaluators/logging-privacy.js.map +1 -1
- package/dist/evaluators/maintainability.d.ts.map +1 -1
- package/dist/evaluators/maintainability.js +9 -0
- package/dist/evaluators/maintainability.js.map +1 -1
- package/dist/evaluators/observability.js +5 -5
- package/dist/evaluators/observability.js.map +1 -1
- package/dist/evaluators/performance.d.ts.map +1 -1
- package/dist/evaluators/performance.js +4 -4
- package/dist/evaluators/performance.js.map +1 -1
- package/dist/evaluators/portability.js +9 -9
- package/dist/evaluators/portability.js.map +1 -1
- package/dist/evaluators/project.d.ts.map +1 -1
- package/dist/evaluators/project.js +84 -1
- package/dist/evaluators/project.js.map +1 -1
- package/dist/evaluators/rate-limiting.d.ts.map +1 -1
- package/dist/evaluators/rate-limiting.js +9 -9
- package/dist/evaluators/rate-limiting.js.map +1 -1
- package/dist/evaluators/reliability.js +4 -4
- package/dist/evaluators/reliability.js.map +1 -1
- package/dist/evaluators/scalability.d.ts.map +1 -1
- package/dist/evaluators/scalability.js +10 -10
- package/dist/evaluators/scalability.js.map +1 -1
- package/dist/evaluators/shared.d.ts +48 -0
- package/dist/evaluators/shared.d.ts.map +1 -1
- package/dist/evaluators/shared.js +197 -0
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/software-practices.js +3 -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 -5
- package/dist/evaluators/testing.js.map +1 -1
- package/dist/evaluators/ux.d.ts.map +1 -1
- package/dist/evaluators/ux.js +19 -19
- package/dist/evaluators/ux.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getLineNumbers, getLangLineNumbers, getLangFamily } from "./shared.js";
|
|
1
|
+
import { getLineNumbers, getLangLineNumbers, getLangFamily, testCode } from "./shared.js";
|
|
2
2
|
import * as LP from "../language-patterns.js";
|
|
3
3
|
export function analyzeRateLimiting(code, language) {
|
|
4
4
|
const findings = [];
|
|
@@ -8,7 +8,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
8
8
|
// No rate limiting middleware (multi-language server detection)
|
|
9
9
|
const hasRateLimit = /rate.?limit|throttle|express-rate-limit|koa-ratelimit|bottleneck|p-limit|limiter|quota|@RateLimiter|RateLimitMiddleware|rate_limit/gi.test(code);
|
|
10
10
|
const routeLines = getLangLineNumbers(code, language, LP.HTTP_ROUTE);
|
|
11
|
-
const hasServerCode = routeLines.length > 0 || /createServer|express\(\)|new\s+Hono/gi
|
|
11
|
+
const hasServerCode = routeLines.length > 0 || testCode(code, /createServer|express\(\)|new\s+Hono/gi);
|
|
12
12
|
if (hasServerCode && !hasRateLimit && code.split("\n").length > 20) {
|
|
13
13
|
findings.push({
|
|
14
14
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -25,7 +25,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
25
25
|
}
|
|
26
26
|
// No request body size limit
|
|
27
27
|
const hasBodyParser = /bodyParser|express\.json|express\.urlencoded|body-parser|app\.use\s*\(\s*express\.json/gi.test(code);
|
|
28
|
-
const hasBodyLimit = /limit\s*:\s*["'`]\d|maxSize|maxBodySize|maxContentLength|payloadLimit/gi
|
|
28
|
+
const hasBodyLimit = testCode(code, /limit\s*:\s*["'`]\d|maxSize|maxBodySize|maxContentLength|payloadLimit/gi);
|
|
29
29
|
if (hasBodyParser && !hasBodyLimit) {
|
|
30
30
|
findings.push({
|
|
31
31
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -104,7 +104,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
104
104
|
// Auth endpoints without stricter rate limits
|
|
105
105
|
const authRoutePattern = /(?:post|put)\s*\(\s*['"]\/(?:auth|login|signin|register|signup|password|reset|forgot|token|oauth)/gi;
|
|
106
106
|
const authRouteLines = getLineNumbers(code, authRoutePattern);
|
|
107
|
-
const hasRateLimiter = /rateLimit|rateLimiter|rate_limit|throttle/gi
|
|
107
|
+
const hasRateLimiter = testCode(code, /rateLimit|rateLimiter|rate_limit|throttle/gi);
|
|
108
108
|
if (authRouteLines.length > 0 && !hasRateLimiter) {
|
|
109
109
|
findings.push({
|
|
110
110
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -121,7 +121,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
121
121
|
// File upload without size limit
|
|
122
122
|
const uploadPattern = /multer\s*\(|upload\s*\.\s*(?:single|array|fields)|formidable|busboy|multipart/gi;
|
|
123
123
|
const uploadLines = getLineNumbers(code, uploadPattern);
|
|
124
|
-
const hasUploadLimit = /limits\s*:\s*\{|maxFileSize|fileSizeLimit|maxFiles/gi
|
|
124
|
+
const hasUploadLimit = testCode(code, /limits\s*:\s*\{|maxFileSize|fileSizeLimit|maxFiles/gi);
|
|
125
125
|
if (uploadLines.length > 0 && !hasUploadLimit) {
|
|
126
126
|
findings.push({
|
|
127
127
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -136,8 +136,8 @@ export function analyzeRateLimiting(code, language) {
|
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
138
|
// Missing 429 status code responses
|
|
139
|
-
const has429 = /429|Too Many Requests|too_many_requests|RATE_LIMIT|rateLimited/gi
|
|
140
|
-
const hasApiEndpoints = /app\.\s*(?:get|post|put|delete|patch)\s*\(|router\.\s*(?:get|post|put|delete|patch)\s*\(/gi
|
|
139
|
+
const has429 = testCode(code, /429|Too Many Requests|too_many_requests|RATE_LIMIT|rateLimited/gi);
|
|
140
|
+
const hasApiEndpoints = testCode(code, /app\.\s*(?:get|post|put|delete|patch)\s*\(|router\.\s*(?:get|post|put|delete|patch)\s*\(/gi);
|
|
141
141
|
if (hasApiEndpoints && !has429 && !hasRateLimiter) {
|
|
142
142
|
findings.push({
|
|
143
143
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -154,7 +154,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
154
154
|
// WebSocket connections without limits
|
|
155
155
|
const wsPattern = /new\s+WebSocket(?:Server)?|wss?\.\s*on\s*\(\s*['"]connection/gi;
|
|
156
156
|
const wsLines = getLineNumbers(code, wsPattern);
|
|
157
|
-
const hasWsLimit = /maxPayload|maxConnections|maxClientsCount|perMessageDeflate.*threshold/gi
|
|
157
|
+
const hasWsLimit = testCode(code, /maxPayload|maxConnections|maxClientsCount|perMessageDeflate.*threshold/gi);
|
|
158
158
|
if (wsLines.length > 0 && !hasWsLimit) {
|
|
159
159
|
findings.push({
|
|
160
160
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -171,7 +171,7 @@ export function analyzeRateLimiting(code, language) {
|
|
|
171
171
|
// Recursive/infinite retry without backoff
|
|
172
172
|
const retryPattern = /retry|retryCount|maxRetries|attempts?\s*[<>]/gi;
|
|
173
173
|
const retryLines = getLineNumbers(code, retryPattern);
|
|
174
|
-
const hasBackoffStrategy = /backoff|exponential|delay\s*\*|Math\.pow|jitter|p-retry|axios-retry|retry-axios|got\.retry|ky\.retry/gi
|
|
174
|
+
const hasBackoffStrategy = testCode(code, /backoff|exponential|delay\s*\*|Math\.pow|jitter|p-retry|axios-retry|retry-axios|got\.retry|ky\.retry/gi);
|
|
175
175
|
if (retryLines.length > 0 && !hasBackoffStrategy) {
|
|
176
176
|
findings.push({
|
|
177
177
|
ruleId: `${prefix}-${String(ruleNum).padStart(3, "0")}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiting.js","sourceRoot":"","sources":["../../src/evaluators/rate-limiting.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limiting.js","sourceRoot":"","sources":["../../src/evaluators/rate-limiting.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAE9C,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,QAAgB;IAChE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEtC,gEAAgE;IAChE,MAAM,YAAY,GAChB,sIAAsI,CAAC,IAAI,CACzI,IAAI,CACL,CAAC;IACJ,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;IACrE,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;IACvG,IAAI,aAAa,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACnE,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,mCAAmC;YAC1C,WAAW,EACT,gKAAgK;YAClK,cAAc,EACZ,qIAAqI;YACvI,SAAS,EAAE,qEAAqE;YAChF,YAAY,EACV,mKAAmK;YACrK,UAAU,EAAE,IAAI;YAChB,cAAc,EAAE,IAAI;YACpB,UAAU,EAAE,oBAAoB;SACjC,CAAC,CAAC;IACL,CAAC;IAED,6BAA6B;IAC7B,MAAM,aAAa,GAAG,0FAA0F,CAAC,IAAI,CACnH,IAAI,CACL,CAAC;IACF,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,EAAE,yEAAyE,CAAC,CAAC;IAC/G,IAAI,aAAa,IAAI,CAAC,YAAY,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,QAAQ;YAClB,KAAK,EAAE,wCAAwC;YAC/C,WAAW,EACT,8HAA8H;YAChI,cAAc,EACZ,oHAAoH;YACtH,SAAS,EAAE,yCAAyC;YACpD,YAAY,EACV,8HAA8H;YAChI,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,0BAA0B;IAC1B,MAAM,qBAAqB,GAAG,mDAAmD,CAAC;IAClF,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IACnE,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,QAAQ;YAClB,KAAK,EAAE,uCAAuC;YAC9C,WAAW,EAAE,SAAS,cAAc,CAAC,MAAM,+GAA+G;YAC1J,WAAW,EAAE,cAAc;YAC3B,cAAc,EACZ,qHAAqH;YACvH,SAAS,EAAE,2CAA2C;YACtD,YAAY,EACV,uIAAuI;YACzI,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,qCAAqC;IACrC,IAAI,aAAa,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACnE,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,wCAAwC;YAC/C,WAAW,EACT,qIAAqI;YACvI,cAAc,EACZ,4GAA4G;YAC9G,SAAS,EAAE,oCAAoC;YAC/C,YAAY,EACV,mKAAmK;YACrK,UAAU,EAAE,GAAG;YACf,cAAc,EAAE,IAAI;YACpB,UAAU,EAAE,oBAAoB;SACjC,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC;IAC7E,MAAM,UAAU,GACd,8GAA8G,CAAC,IAAI,CACjH,IAAI,CACL,CAAC;IACJ,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChD,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,mDAAmD;YAC1D,WAAW,EAAE,SAAS,iBAAiB,CAAC,MAAM,8JAA8J;YAC5M,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1C,cAAc,EACZ,gKAAgK;YAClK,SAAS,EAAE,oDAAoD;YAC/D,YAAY,EACV,uJAAuJ;YACzJ,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,0DAA0D;IAC1D,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;IAC/C,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAClE,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,KAAK;YACf,KAAK,EAAE,kCAAkC;YACzC,WAAW,EACT,yIAAyI;YAC3I,WAAW,EAAE,gBAAgB;YAC7B,cAAc,EACZ,iJAAiJ;YACnJ,SAAS,EAAE,iCAAiC;YAC5C,YAAY,EACV,kKAAkK;YACpK,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,8CAA8C;IAC9C,MAAM,gBAAgB,GACpB,qGAAqG,CAAC;IACxG,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,EAAE,6CAA6C,CAAC,CAAC;IACrF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,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,MAAM;YAChB,KAAK,EAAE,gDAAgD;YACvD,WAAW,EAAE,SAAS,cAAc,CAAC,MAAM,8IAA8I;YACzL,WAAW,EAAE,cAAc;YAC3B,cAAc,EACZ,0MAA0M;YAC5M,SAAS,EAAE,8CAA8C;YACzD,YAAY,EACV,2GAA2G;YAC7G,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,iCAAiC;IACjC,MAAM,aAAa,GAAG,iFAAiF,CAAC;IACxG,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,EAAE,sDAAsD,CAAC,CAAC;IAC9F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAC9C,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,0CAA0C;YACjD,WAAW,EAAE,SAAS,WAAW,CAAC,MAAM,sIAAsI;YAC9K,WAAW,EAAE,WAAW;YACxB,cAAc,EACZ,sJAAsJ;YACxJ,SAAS,EAAE,iDAAiD;YAC5D,YAAY,EACV,0HAA0H;YAC5H,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,kEAAkE,CAAC,CAAC;IAClG,MAAM,eAAe,GAAG,QAAQ,CAC9B,IAAI,EACJ,4FAA4F,CAC7F,CAAC;IACF,IAAI,eAAe,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAClD,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,wDAAwD;YAC/D,WAAW,EACT,mKAAmK;YACrK,cAAc,EACZ,kKAAkK;YACpK,SAAS,EAAE,8DAA8D;YACzE,YAAY,EACV,6IAA6I;YAC/I,UAAU,EAAE,GAAG;YACf,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC;IACL,CAAC;IAED,uCAAuC;IACvC,MAAM,SAAS,GAAG,gEAAgE,CAAC;IACnF,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,0EAA0E,CAAC,CAAC;IAC9G,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACtC,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,uDAAuD;YAC9D,WAAW,EAAE,SAAS,OAAO,CAAC,MAAM,wIAAwI;YAC5K,WAAW,EAAE,OAAO;YACpB,cAAc,EACZ,oJAAoJ;YACtJ,SAAS,EAAE,oDAAoD;YAC/D,YAAY,EACV,8IAA8I;YAChJ,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,2CAA2C;IAC3C,MAAM,YAAY,GAAG,gDAAgD,CAAC;IACtE,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,QAAQ,CACjC,IAAI,EACJ,wGAAwG,CACzG,CAAC;IACF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACvD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,yCAAyC;YAChD,WAAW,EAAE,SAAS,UAAU,CAAC,MAAM,mJAAmJ;YAC1L,WAAW,EAAE,UAAU;YACvB,cAAc,EACZ,yKAAyK;YAC3K,SAAS,EAAE,uDAAuD;YAClE,YAAY,EACV,0HAA0H;YAC5H,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getLangLineNumbers, getLangFamily, isCommentLine } from "./shared.js";
|
|
1
|
+
import { getLangLineNumbers, getLangFamily, isCommentLine, testCode } from "./shared.js";
|
|
2
2
|
import * as LP from "../language-patterns.js";
|
|
3
3
|
export function analyzeReliability(code, language) {
|
|
4
4
|
const findings = [];
|
|
@@ -56,7 +56,7 @@ export function analyzeReliability(code, language) {
|
|
|
56
56
|
}
|
|
57
57
|
// Detect missing retry logic for transient failures (multi-language)
|
|
58
58
|
const externalCallLines = getLangLineNumbers(code, language, LP.HTTP_CLIENT).concat(getLangLineNumbers(code, language, LP.DB_QUERY));
|
|
59
|
-
const hasRetry = /retry|retries|backoff|exponential|tenacity|Polly|resilience4j|backoff::/i
|
|
59
|
+
const hasRetry = testCode(code, /retry|retries|backoff|exponential|tenacity|Polly|resilience4j|backoff::/i);
|
|
60
60
|
if (externalCallLines.length > 2 && !hasRetry) {
|
|
61
61
|
findings.push({
|
|
62
62
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -131,7 +131,7 @@ export function analyzeReliability(code, language) {
|
|
|
131
131
|
}
|
|
132
132
|
// Circuit breaker pattern missing
|
|
133
133
|
const hasMultipleExternalCalls = externalCallLines.length > 3;
|
|
134
|
-
const hasCircuitBreaker = /circuit.?breaker|CircuitBreaker|opossum|cockatiel|polly/i
|
|
134
|
+
const hasCircuitBreaker = testCode(code, /circuit.?breaker|CircuitBreaker|opossum|cockatiel|polly/i);
|
|
135
135
|
if (hasMultipleExternalCalls && !hasCircuitBreaker) {
|
|
136
136
|
findings.push({
|
|
137
137
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -179,7 +179,7 @@ export function analyzeReliability(code, language) {
|
|
|
179
179
|
writeEndpointLines.push(i + 1);
|
|
180
180
|
}
|
|
181
181
|
});
|
|
182
|
-
const hasIdempotency = /idempoten|idempotency.?key|x-idempotency/i
|
|
182
|
+
const hasIdempotency = testCode(code, /idempoten|idempotency.?key|x-idempotency/i);
|
|
183
183
|
if (writeEndpointLines.length > 2 && !hasIdempotency) {
|
|
184
184
|
findings.push({
|
|
185
185
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reliability.js","sourceRoot":"","sources":["../../src/evaluators/reliability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"reliability.js","sourceRoot":"","sources":["../../src/evaluators/reliability.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,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"scalability.d.ts","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAW3C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAsR5E"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getLineNumbers, getLangLineNumbers, getLangFamily, isIaCTemplate } from "./shared.js";
|
|
1
|
+
import { getLineNumbers, getLangLineNumbers, getLangFamily, isIaCTemplate, testCode, getContextWindow, } from "./shared.js";
|
|
2
2
|
import * as LP from "../language-patterns.js";
|
|
3
3
|
export function analyzeScalability(code, language) {
|
|
4
4
|
const findings = [];
|
|
@@ -60,8 +60,8 @@ export function analyzeScalability(code, language) {
|
|
|
60
60
|
const rawBlockingLines = getLineNumbers(code, blockingPattern);
|
|
61
61
|
// Exclude lines containing 'await' — those are async and non-blocking
|
|
62
62
|
const blockingLines = rawBlockingLines.filter((ln) => {
|
|
63
|
-
const
|
|
64
|
-
return !/\bawait\b/i.test(
|
|
63
|
+
const ctx = getContextWindow(lines, ln, 1);
|
|
64
|
+
return !/\bawait\b/i.test(ctx);
|
|
65
65
|
});
|
|
66
66
|
if (blockingLines.length > 0) {
|
|
67
67
|
findings.push({
|
|
@@ -78,7 +78,7 @@ export function analyzeScalability(code, language) {
|
|
|
78
78
|
}
|
|
79
79
|
// No timeout on external calls (multi-language)
|
|
80
80
|
const fetchLines = getLangLineNumbers(code, language, LP.HTTP_CLIENT);
|
|
81
|
-
const hasTimeout = /timeout|Timeout|deadline|AbortController|Duration|TimeSpan|time\.After/gi
|
|
81
|
+
const hasTimeout = testCode(code, /timeout|Timeout|deadline|AbortController|Duration|TimeSpan|time\.After/gi);
|
|
82
82
|
if (fetchLines.length > 0 && !hasTimeout) {
|
|
83
83
|
findings.push({
|
|
84
84
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -97,7 +97,7 @@ export function analyzeScalability(code, language) {
|
|
|
97
97
|
// Use [^)]* instead of .* to avoid O(n²) backtracking between wildcards and \)
|
|
98
98
|
const heavyCompPattern = /(?:for|while)\s*\([^)]*(?:length|size|count)[^)]*\)[\s\S]{0,200}(?:for|while)\s*\(/gi;
|
|
99
99
|
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;
|
|
100
|
-
const hasNestedLoops =
|
|
100
|
+
const hasNestedLoops = testCode(code, heavyCompPattern);
|
|
101
101
|
const cpuOpsLines = getLineNumbers(code, cpuIntensiveOps);
|
|
102
102
|
if (hasNestedLoops || cpuOpsLines.length > 0) {
|
|
103
103
|
findings.push({
|
|
@@ -113,7 +113,7 @@ export function analyzeScalability(code, language) {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
// No rate limiting detected
|
|
116
|
-
const hasRateLimit = /rate.?limit|throttle|limiter|RateLimit/gi
|
|
116
|
+
const hasRateLimit = testCode(code, /rate.?limit|throttle|limiter|RateLimit/gi);
|
|
117
117
|
const iacTemplate = isIaCTemplate(code);
|
|
118
118
|
if (!hasRateLimit && fetchLines.length > 0 && !iacTemplate) {
|
|
119
119
|
findings.push({
|
|
@@ -147,7 +147,7 @@ export function analyzeScalability(code, language) {
|
|
|
147
147
|
// Sticky session / session affinity assumptions
|
|
148
148
|
const stickySessionPattern = /session\s*\{|express-session|SessionMiddleware|sticky|affinity/gi;
|
|
149
149
|
const stickySessionLines = getLineNumbers(code, stickySessionPattern);
|
|
150
|
-
const hasExternalSession = /redis|memcached|dynamodb|MongoStore|connect-redis|connect-mongo/gi
|
|
150
|
+
const hasExternalSession = testCode(code, /redis|memcached|dynamodb|MongoStore|connect-redis|connect-mongo/gi);
|
|
151
151
|
if (stickySessionLines.length > 0 && !hasExternalSession) {
|
|
152
152
|
findings.push({
|
|
153
153
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
@@ -178,7 +178,7 @@ export function analyzeScalability(code, language) {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
// No circuit breaker pattern
|
|
181
|
-
const hasCircuitBreaker = /circuit.?breaker|opossum|cockatiel|polly|resilience4j|hystrix|CircuitBreaker/gi
|
|
181
|
+
const hasCircuitBreaker = testCode(code, /circuit.?breaker|opossum|cockatiel|polly|resilience4j|hystrix|CircuitBreaker/gi);
|
|
182
182
|
const hasMultipleExternalCalls = fetchLines.length > 2;
|
|
183
183
|
if (hasMultipleExternalCalls && !hasCircuitBreaker && !iacTemplate) {
|
|
184
184
|
findings.push({
|
|
@@ -195,7 +195,7 @@ export function analyzeScalability(code, language) {
|
|
|
195
195
|
}
|
|
196
196
|
// Monolithic query / large payload assembly
|
|
197
197
|
const largePayloadPattern = /JSON\.stringify\s*\(.*\bdata\b|res\.json\s*\(\s*\{[\s\S]{0,50}\.findAll|\.aggregate\s*\(\s*\[[\s\S]{200,}/gi;
|
|
198
|
-
if (
|
|
198
|
+
if (testCode(code, largePayloadPattern)) {
|
|
199
199
|
findings.push({
|
|
200
200
|
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
201
201
|
severity: "low",
|
|
@@ -210,7 +210,7 @@ export function analyzeScalability(code, language) {
|
|
|
210
210
|
// WebSocket without connection limits
|
|
211
211
|
const wsPattern = /WebSocket|ws\s*\(|socket\.io|Socket\s*\(|socketserver/gi;
|
|
212
212
|
const wsLines = getLineNumbers(code, wsPattern);
|
|
213
|
-
const hasWsLimit = /maxPayload|maxConnections|connectionLimit|max_connections/gi
|
|
213
|
+
const hasWsLimit = testCode(code, /maxPayload|maxConnections|connectionLimit|max_connections/gi);
|
|
214
214
|
if (wsLines.length > 0 && !hasWsLimit) {
|
|
215
215
|
findings.push({
|
|
216
216
|
ruleId: `${prefix}-${String(ruleNum).padStart(3, "0")}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scalability.js","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"scalability.js","sourceRoot":"","sources":["../../src/evaluators/scalability.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,54 @@ export declare function isCommentLine(line: string): boolean;
|
|
|
48
48
|
* skip these lines to avoid false positives from example code in strings.
|
|
49
49
|
*/
|
|
50
50
|
export declare function isStringLiteralLine(line: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Strip all comments from source code, replacing their content with spaces.
|
|
53
|
+
* String literals are preserved so that import paths and require() arguments
|
|
54
|
+
* remain matchable. Line structure (newlines) is preserved so that line
|
|
55
|
+
* numbers remain stable.
|
|
56
|
+
*
|
|
57
|
+
* Handles:
|
|
58
|
+
* - Single-line comments: `//`, `#` (Python/Ruby/YAML)
|
|
59
|
+
* - Block comments: slash-star ... star-slash
|
|
60
|
+
* - Python docstrings: `"""..."""` / `'''...'''` (treated as comments)
|
|
61
|
+
*
|
|
62
|
+
* Strings (`"..."`, `'...'`, `` `...` ``) are skipped (preserved) to avoid
|
|
63
|
+
* breaking patterns that intentionally match import paths, require() calls,
|
|
64
|
+
* route strings, etc.
|
|
65
|
+
*
|
|
66
|
+
* This is intentionally a lightweight heuristic — the goal is to eliminate
|
|
67
|
+
* the most common FP source (patterns in comments) without the overhead of
|
|
68
|
+
* a full parser.
|
|
69
|
+
*/
|
|
70
|
+
export declare function stripCommentsAndStrings(code: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Test whether a regex pattern matches in executable code (ignoring
|
|
73
|
+
* comments). String literals are preserved so that import paths, require()
|
|
74
|
+
* arguments, and route strings remain matchable. Drop-in replacement for
|
|
75
|
+
* `pattern.test(code)` that strips comments first.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* // Instead of:
|
|
80
|
+
* const hasRateLimit = /rateLimit/i.test(code);
|
|
81
|
+
* // Use:
|
|
82
|
+
* const hasRateLimit = testCode(code, /rateLimit/i);
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function testCode(code: string, pattern: RegExp): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Get a multi-line context window around a specific line number.
|
|
88
|
+
* Returns the concatenated text of lines within ±radius of the target line.
|
|
89
|
+
* Useful for post-match filtering where the relevant pattern (e.g., a
|
|
90
|
+
* fallback operator `??`/`||`, an `await`, a config block brace) may appear
|
|
91
|
+
* on an adjacent line rather than the matched line itself.
|
|
92
|
+
*
|
|
93
|
+
* @param lines Array of source code lines (0-indexed)
|
|
94
|
+
* @param lineNum 1-based line number (as returned by getLineNumbers)
|
|
95
|
+
* @param radius Number of lines to include before and after (default 3)
|
|
96
|
+
* @returns Concatenated text of lines in the window
|
|
97
|
+
*/
|
|
98
|
+
export declare function getContextWindow(lines: string[], lineNum: number, radius?: number): string;
|
|
51
99
|
/**
|
|
52
100
|
* Find line numbers in source code that match a given regex pattern.
|
|
53
101
|
* By default, comment lines and string-literal-only lines are skipped
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/evaluators/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,OAAO,EAEP,OAAO,EACP,YAAY,EACZ,UAAU,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAS,MAAM,yBAAyB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAC;AAW1C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAOD,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,CAAC;AAEd;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CA+G5F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAErE;AAID,+EAA+E;AAC/E,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAkDvC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAmBpF;AAcD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAcD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/evaluators/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -232,6 +232,203 @@ const STRING_LITERAL_LINE_RE = /^\s*["'`].*["'`][,;]?\s*$/;
|
|
|
232
232
|
export function isStringLiteralLine(line) {
|
|
233
233
|
return STRING_LITERAL_LINE_RE.test(line);
|
|
234
234
|
}
|
|
235
|
+
// ─── Comment & String Stripping ──────────────────────────────────────────────
|
|
236
|
+
// Provides `stripCommentsAndStrings()` which replaces all comments and string
|
|
237
|
+
// literals with whitespace (preserving line structure) so that whole-file
|
|
238
|
+
// boolean checks like `pattern.test(code)` don't match patterns that exist
|
|
239
|
+
// only in comments, strings, or documentation.
|
|
240
|
+
//
|
|
241
|
+
// `testCode()` is a convenience wrapper: it lazily strips the code on first
|
|
242
|
+
// call and caches the result for subsequent tests against the same source.
|
|
243
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
244
|
+
/**
|
|
245
|
+
* Strip all comments from source code, replacing their content with spaces.
|
|
246
|
+
* String literals are preserved so that import paths and require() arguments
|
|
247
|
+
* remain matchable. Line structure (newlines) is preserved so that line
|
|
248
|
+
* numbers remain stable.
|
|
249
|
+
*
|
|
250
|
+
* Handles:
|
|
251
|
+
* - Single-line comments: `//`, `#` (Python/Ruby/YAML)
|
|
252
|
+
* - Block comments: slash-star ... star-slash
|
|
253
|
+
* - Python docstrings: `"""..."""` / `'''...'''` (treated as comments)
|
|
254
|
+
*
|
|
255
|
+
* Strings (`"..."`, `'...'`, `` `...` ``) are skipped (preserved) to avoid
|
|
256
|
+
* breaking patterns that intentionally match import paths, require() calls,
|
|
257
|
+
* route strings, etc.
|
|
258
|
+
*
|
|
259
|
+
* This is intentionally a lightweight heuristic — the goal is to eliminate
|
|
260
|
+
* the most common FP source (patterns in comments) without the overhead of
|
|
261
|
+
* a full parser.
|
|
262
|
+
*/
|
|
263
|
+
export function stripCommentsAndStrings(code) {
|
|
264
|
+
const len = code.length;
|
|
265
|
+
const result = new Array(len);
|
|
266
|
+
let i = 0;
|
|
267
|
+
while (i < len) {
|
|
268
|
+
const ch = code[i];
|
|
269
|
+
const next = i + 1 < len ? code[i + 1] : "";
|
|
270
|
+
// ── Single-line comment: // ──
|
|
271
|
+
if (ch === "/" && next === "/") {
|
|
272
|
+
while (i < len && code[i] !== "\n") {
|
|
273
|
+
result[i] = " ";
|
|
274
|
+
i++;
|
|
275
|
+
}
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
// ── Block comment: /* ... */ ──
|
|
279
|
+
if (ch === "/" && next === "*") {
|
|
280
|
+
result[i] = " ";
|
|
281
|
+
result[i + 1] = " ";
|
|
282
|
+
i += 2;
|
|
283
|
+
while (i < len) {
|
|
284
|
+
if (code[i] === "\n") {
|
|
285
|
+
result[i] = "\n";
|
|
286
|
+
i++;
|
|
287
|
+
}
|
|
288
|
+
else if (code[i] === "*" && i + 1 < len && code[i + 1] === "/") {
|
|
289
|
+
result[i] = " ";
|
|
290
|
+
result[i + 1] = " ";
|
|
291
|
+
i += 2;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
result[i] = " ";
|
|
296
|
+
i++;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
// ── Python-style `#` comment (but not `#!`, `#[` for Rust attributes) ──
|
|
302
|
+
if (ch === "#" && next !== "!" && next !== "[") {
|
|
303
|
+
while (i < len && code[i] !== "\n") {
|
|
304
|
+
result[i] = " ";
|
|
305
|
+
i++;
|
|
306
|
+
}
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
// ── Python triple-quoted strings / docstrings — treat as comments ──
|
|
310
|
+
if ((ch === '"' && next === '"' && i + 2 < len && code[i + 2] === '"') ||
|
|
311
|
+
(ch === "'" && next === "'" && i + 2 < len && code[i + 2] === "'")) {
|
|
312
|
+
const quote3 = code.substring(i, i + 3);
|
|
313
|
+
result[i] = " ";
|
|
314
|
+
result[i + 1] = " ";
|
|
315
|
+
result[i + 2] = " ";
|
|
316
|
+
i += 3;
|
|
317
|
+
while (i < len) {
|
|
318
|
+
if (code[i] === "\n") {
|
|
319
|
+
result[i] = "\n";
|
|
320
|
+
i++;
|
|
321
|
+
}
|
|
322
|
+
else if (code.substring(i, i + 3) === quote3) {
|
|
323
|
+
result[i] = " ";
|
|
324
|
+
result[i + 1] = " ";
|
|
325
|
+
result[i + 2] = " ";
|
|
326
|
+
i += 3;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
result[i] = " ";
|
|
331
|
+
i++;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
// ── String literals: "...", '...', `...` — SKIP (preserve) ──
|
|
337
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
338
|
+
const quote = ch;
|
|
339
|
+
result[i] = ch; // keep opening quote
|
|
340
|
+
i++;
|
|
341
|
+
while (i < len) {
|
|
342
|
+
if (code[i] === "\\") {
|
|
343
|
+
result[i] = code[i];
|
|
344
|
+
i++;
|
|
345
|
+
if (i < len) {
|
|
346
|
+
result[i] = code[i];
|
|
347
|
+
i++;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else if (code[i] === "\n" && quote !== "`") {
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
else if (code[i] === quote) {
|
|
354
|
+
result[i] = ch; // keep closing quote
|
|
355
|
+
i++;
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
result[i] = code[i]; // preserve string content
|
|
360
|
+
i++;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
// ── Plain content — keep as-is ──
|
|
366
|
+
result[i] = ch;
|
|
367
|
+
i++;
|
|
368
|
+
}
|
|
369
|
+
return result.join("");
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* LRU-style cache for stripped code. Uses a WeakRef-based approach keyed
|
|
373
|
+
* by the code string itself (via a simple Map with bounded size).
|
|
374
|
+
*/
|
|
375
|
+
const strippedCodeCache = new Map();
|
|
376
|
+
const MAX_STRIPPED_CACHE = 64;
|
|
377
|
+
/**
|
|
378
|
+
* Get or create a stripped version of the source code. Results are cached
|
|
379
|
+
* per unique `code` string so that multiple `testCode()` calls in the same
|
|
380
|
+
* evaluator invocation share one strip pass.
|
|
381
|
+
*/
|
|
382
|
+
function getStrippedCode(code) {
|
|
383
|
+
let stripped = strippedCodeCache.get(code);
|
|
384
|
+
if (stripped !== undefined)
|
|
385
|
+
return stripped;
|
|
386
|
+
stripped = stripCommentsAndStrings(code);
|
|
387
|
+
// Evict oldest entry if cache is full
|
|
388
|
+
if (strippedCodeCache.size >= MAX_STRIPPED_CACHE) {
|
|
389
|
+
const first = strippedCodeCache.keys().next().value;
|
|
390
|
+
if (first !== undefined)
|
|
391
|
+
strippedCodeCache.delete(first);
|
|
392
|
+
}
|
|
393
|
+
strippedCodeCache.set(code, stripped);
|
|
394
|
+
return stripped;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Test whether a regex pattern matches in executable code (ignoring
|
|
398
|
+
* comments). String literals are preserved so that import paths, require()
|
|
399
|
+
* arguments, and route strings remain matchable. Drop-in replacement for
|
|
400
|
+
* `pattern.test(code)` that strips comments first.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* // Instead of:
|
|
405
|
+
* const hasRateLimit = /rateLimit/i.test(code);
|
|
406
|
+
* // Use:
|
|
407
|
+
* const hasRateLimit = testCode(code, /rateLimit/i);
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
export function testCode(code, pattern) {
|
|
411
|
+
const stripped = getStrippedCode(code);
|
|
412
|
+
pattern.lastIndex = 0;
|
|
413
|
+
return pattern.test(stripped);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get a multi-line context window around a specific line number.
|
|
417
|
+
* Returns the concatenated text of lines within ±radius of the target line.
|
|
418
|
+
* Useful for post-match filtering where the relevant pattern (e.g., a
|
|
419
|
+
* fallback operator `??`/`||`, an `await`, a config block brace) may appear
|
|
420
|
+
* on an adjacent line rather than the matched line itself.
|
|
421
|
+
*
|
|
422
|
+
* @param lines Array of source code lines (0-indexed)
|
|
423
|
+
* @param lineNum 1-based line number (as returned by getLineNumbers)
|
|
424
|
+
* @param radius Number of lines to include before and after (default 3)
|
|
425
|
+
* @returns Concatenated text of lines in the window
|
|
426
|
+
*/
|
|
427
|
+
export function getContextWindow(lines, lineNum, radius = 3) {
|
|
428
|
+
const start = Math.max(0, lineNum - 1 - radius);
|
|
429
|
+
const end = Math.min(lines.length, lineNum + radius);
|
|
430
|
+
return lines.slice(start, end).join("\n");
|
|
431
|
+
}
|
|
235
432
|
/**
|
|
236
433
|
* Find line numbers in source code that match a given regex pattern.
|
|
237
434
|
* By default, comment lines and string-literal-only lines are skipped
|