@codacy/analysis-runner 0.6.1 → 0.8.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/dist/index.d.ts +131 -7
- package/dist/index.js +1199 -32
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -34,15 +34,18 @@ __export(index_exports, {
|
|
|
34
34
|
applyCodacyYamlExcludes: () => applyCodacyYamlExcludes,
|
|
35
35
|
buildToolConfig: () => buildToolConfig,
|
|
36
36
|
clearAdapters: () => clearAdapters,
|
|
37
|
+
computePatternSummary: () => computePatternSummary,
|
|
37
38
|
configureApiToken: () => configureApiToken,
|
|
38
39
|
createCodacyConfig: () => createCodacyConfig,
|
|
39
40
|
createLogger: () => createLogger,
|
|
40
41
|
detectLanguages: () => detectLanguages,
|
|
42
|
+
discover: () => discover,
|
|
41
43
|
formatOutput: () => formatOutput,
|
|
42
44
|
formatTextSummary: () => formatTextSummary,
|
|
43
45
|
getAdapter: () => getAdapter,
|
|
44
46
|
getRegisteredAdapters: () => getRegisteredAdapters,
|
|
45
47
|
getRegisteredDescriptors: () => getRegisteredDescriptors,
|
|
48
|
+
initAutoConfig: () => initAutoConfig,
|
|
46
49
|
initContainerConfig: () => initContainerConfig,
|
|
47
50
|
initDefaultConfig: () => initDefaultConfig,
|
|
48
51
|
initLocalConfig: () => initLocalConfig,
|
|
@@ -51,6 +54,7 @@ __export(index_exports, {
|
|
|
51
54
|
listIgnoredFiles: () => listIgnoredFiles,
|
|
52
55
|
listPrFiles: () => listPrFiles,
|
|
53
56
|
listStagedFiles: () => listStagedFiles,
|
|
57
|
+
parseAutoFilters: () => parseAutoFilters,
|
|
54
58
|
readCodacyConfig: () => readCodacyConfig,
|
|
55
59
|
readCodacyYaml: () => readCodacyYaml,
|
|
56
60
|
registerAdapter: () => registerAdapter,
|
|
@@ -192,6 +196,7 @@ function createCodacyConfig(params = {}) {
|
|
|
192
196
|
source: params.source ?? "local",
|
|
193
197
|
provider: params.provider ?? null,
|
|
194
198
|
organization: params.organization ?? null,
|
|
199
|
+
autoFilters: params.autoFilters,
|
|
195
200
|
repositoryId: params.repositoryId ?? null,
|
|
196
201
|
repositoryName: params.repositoryName ?? null,
|
|
197
202
|
createdAt: now,
|
|
@@ -460,6 +465,116 @@ async function runToolsParallel(tools, timeoutMs, concurrency, callbacks) {
|
|
|
460
465
|
return results;
|
|
461
466
|
}
|
|
462
467
|
|
|
468
|
+
// src/summary.ts
|
|
469
|
+
var NOISY_THRESHOLD = 500;
|
|
470
|
+
var SEVERITY_ORDER = ["Error", "High", "Warning", "Info"];
|
|
471
|
+
var SEVERITY_LABELS = {
|
|
472
|
+
Error: "CRITICAL",
|
|
473
|
+
High: "HIGH",
|
|
474
|
+
Warning: "WARNING",
|
|
475
|
+
Info: "MINOR"
|
|
476
|
+
};
|
|
477
|
+
var CATEGORY_ORDER = [
|
|
478
|
+
"Security",
|
|
479
|
+
"ErrorProne",
|
|
480
|
+
"Performance",
|
|
481
|
+
"BestPractice",
|
|
482
|
+
"UnusedCode",
|
|
483
|
+
"Compatibility",
|
|
484
|
+
"Complexity",
|
|
485
|
+
"Comprehensibility",
|
|
486
|
+
"CodeStyle",
|
|
487
|
+
"Documentation"
|
|
488
|
+
];
|
|
489
|
+
function formatCategoryName(category) {
|
|
490
|
+
return category.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
491
|
+
}
|
|
492
|
+
function computePatternSummary(issues, lookup) {
|
|
493
|
+
if (issues.length === 0) {
|
|
494
|
+
return {
|
|
495
|
+
groups: [],
|
|
496
|
+
totalIssues: 0,
|
|
497
|
+
totalPatterns: 0,
|
|
498
|
+
noisyPatternCount: 0,
|
|
499
|
+
noisyThreshold: NOISY_THRESHOLD
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const accumMap = /* @__PURE__ */ new Map();
|
|
503
|
+
for (const issue of issues) {
|
|
504
|
+
const key = `${issue.toolId}|${issue.severity}|${issue.category}|${issue.patternId}`;
|
|
505
|
+
let accum = accumMap.get(key);
|
|
506
|
+
if (!accum) {
|
|
507
|
+
accum = {
|
|
508
|
+
patternId: issue.patternId,
|
|
509
|
+
toolId: issue.toolId,
|
|
510
|
+
severity: issue.severity,
|
|
511
|
+
category: issue.category,
|
|
512
|
+
issueCount: 0,
|
|
513
|
+
files: /* @__PURE__ */ new Set()
|
|
514
|
+
};
|
|
515
|
+
accumMap.set(key, accum);
|
|
516
|
+
}
|
|
517
|
+
accum.issueCount++;
|
|
518
|
+
accum.files.add(issue.filePath);
|
|
519
|
+
}
|
|
520
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
521
|
+
for (const accum of accumMap.values()) {
|
|
522
|
+
const groupKey = `${accum.severity}|${accum.category}`;
|
|
523
|
+
let list = groupMap.get(groupKey);
|
|
524
|
+
if (!list) {
|
|
525
|
+
list = [];
|
|
526
|
+
groupMap.set(groupKey, list);
|
|
527
|
+
}
|
|
528
|
+
list.push(accum);
|
|
529
|
+
}
|
|
530
|
+
let totalPatterns = 0;
|
|
531
|
+
let noisyPatternCount = 0;
|
|
532
|
+
const groups = [];
|
|
533
|
+
for (const severity of SEVERITY_ORDER) {
|
|
534
|
+
for (const category of CATEGORY_ORDER) {
|
|
535
|
+
const accums = groupMap.get(`${severity}|${category}`);
|
|
536
|
+
if (!accums || accums.length === 0) continue;
|
|
537
|
+
accums.sort((a, b) => b.issueCount - a.issueCount);
|
|
538
|
+
let groupIssueCount = 0;
|
|
539
|
+
const patterns = [];
|
|
540
|
+
for (const acc of accums) {
|
|
541
|
+
const meta = lookup.get(`${acc.toolId}|${acc.patternId}`);
|
|
542
|
+
const noisy = acc.issueCount >= NOISY_THRESHOLD;
|
|
543
|
+
if (noisy) noisyPatternCount++;
|
|
544
|
+
totalPatterns++;
|
|
545
|
+
groupIssueCount += acc.issueCount;
|
|
546
|
+
patterns.push({
|
|
547
|
+
patternId: acc.patternId,
|
|
548
|
+
title: meta?.title ?? acc.patternId,
|
|
549
|
+
toolId: acc.toolId,
|
|
550
|
+
toolDisplayName: meta?.toolDisplayName ?? acc.toolId,
|
|
551
|
+
category,
|
|
552
|
+
severity,
|
|
553
|
+
issueCount: acc.issueCount,
|
|
554
|
+
fileCount: acc.files.size,
|
|
555
|
+
noisy
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
groups.push({
|
|
559
|
+
severity,
|
|
560
|
+
severityLabel: SEVERITY_LABELS[severity],
|
|
561
|
+
category,
|
|
562
|
+
categoryLabel: formatCategoryName(category),
|
|
563
|
+
patterns,
|
|
564
|
+
totalIssues: groupIssueCount,
|
|
565
|
+
totalPatterns: patterns.length
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return {
|
|
570
|
+
groups,
|
|
571
|
+
totalIssues: issues.length,
|
|
572
|
+
totalPatterns,
|
|
573
|
+
noisyPatternCount,
|
|
574
|
+
noisyThreshold: NOISY_THRESHOLD
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
463
578
|
// src/analyze.ts
|
|
464
579
|
var execFileAsync = (0, import_util.promisify)(import_child_process2.execFile);
|
|
465
580
|
var nullLogger = {
|
|
@@ -831,6 +946,18 @@ async function analyze(options) {
|
|
|
831
946
|
const allIssues = normalizeIssues(results.flatMap((r) => r.issues));
|
|
832
947
|
const allErrors = results.flatMap((r) => r.errors);
|
|
833
948
|
const allSummaries = results.map((r) => r.summary);
|
|
949
|
+
const patternLookup = /* @__PURE__ */ new Map();
|
|
950
|
+
for (const { adapter } of toolRuns) {
|
|
951
|
+
if (adapter.patternsMetadata) {
|
|
952
|
+
for (const entry of adapter.patternsMetadata) {
|
|
953
|
+
patternLookup.set(`${adapter.id}|${entry.id}`, {
|
|
954
|
+
title: entry.title,
|
|
955
|
+
toolDisplayName: adapter.displayName
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
const patternSummary = allIssues.length > 0 ? computePatternSummary(allIssues, patternLookup) : void 0;
|
|
834
961
|
logger.info("Pipeline complete", {
|
|
835
962
|
totalIssues: allIssues.length,
|
|
836
963
|
totalErrors: allErrors.length,
|
|
@@ -843,7 +970,8 @@ async function analyze(options) {
|
|
|
843
970
|
capability,
|
|
844
971
|
allIssues,
|
|
845
972
|
allErrors,
|
|
846
|
-
allSummaries
|
|
973
|
+
allSummaries,
|
|
974
|
+
patternSummary
|
|
847
975
|
);
|
|
848
976
|
}
|
|
849
977
|
function makeToolContext(base, adapter, targetFiles) {
|
|
@@ -869,7 +997,7 @@ function resolveGitScope(repositoryRoot, scope) {
|
|
|
869
997
|
const base = scope.diff === true ? void 0 : scope.diff;
|
|
870
998
|
return listDiffFiles(repositoryRoot, base);
|
|
871
999
|
}
|
|
872
|
-
function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults) {
|
|
1000
|
+
function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults, patternSummary) {
|
|
873
1001
|
const completedAt = /* @__PURE__ */ new Date();
|
|
874
1002
|
return {
|
|
875
1003
|
metadata: {
|
|
@@ -882,7 +1010,8 @@ function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors
|
|
|
882
1010
|
capability,
|
|
883
1011
|
issues,
|
|
884
1012
|
errors,
|
|
885
|
-
toolResults
|
|
1013
|
+
toolResults,
|
|
1014
|
+
...patternSummary ? { patternSummary } : {}
|
|
886
1015
|
};
|
|
887
1016
|
}
|
|
888
1017
|
|
|
@@ -1159,6 +1288,11 @@ function formatTextSummary(result, isInspect) {
|
|
|
1159
1288
|
}
|
|
1160
1289
|
}
|
|
1161
1290
|
}
|
|
1291
|
+
const patternSummaryText = formatPatternSummary(result.patternSummary);
|
|
1292
|
+
if (patternSummaryText) {
|
|
1293
|
+
lines.push("");
|
|
1294
|
+
lines.push(patternSummaryText);
|
|
1295
|
+
}
|
|
1162
1296
|
return lines.join("\n");
|
|
1163
1297
|
}
|
|
1164
1298
|
var MAX_LINE_LENGTH = 100;
|
|
@@ -1241,23 +1375,801 @@ function colorSeverity(severity) {
|
|
|
1241
1375
|
return `[${severity}]`;
|
|
1242
1376
|
}
|
|
1243
1377
|
}
|
|
1378
|
+
function severityColorFn(severity) {
|
|
1379
|
+
switch (severity) {
|
|
1380
|
+
case "Error":
|
|
1381
|
+
return (s) => import_ansis.default.hex("#ff6347")(s);
|
|
1382
|
+
case "High":
|
|
1383
|
+
return (s) => import_ansis.default.hex("#ff8c00")(s);
|
|
1384
|
+
case "Warning":
|
|
1385
|
+
return (s) => import_ansis.default.hex("#ffd700")(s);
|
|
1386
|
+
case "Info":
|
|
1387
|
+
return (s) => import_ansis.default.cyan(s);
|
|
1388
|
+
default:
|
|
1389
|
+
return (s) => s;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
var MAX_PATTERNS_PER_GROUP = 10;
|
|
1393
|
+
function formatPatternSummary(summary) {
|
|
1394
|
+
if (!summary || summary.groups.length === 0) return "";
|
|
1395
|
+
const lines = [];
|
|
1396
|
+
lines.push(import_ansis.default.bold("Pattern Summary"));
|
|
1397
|
+
lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1398
|
+
if (summary.noisyPatternCount > 0) {
|
|
1399
|
+
const n = summary.noisyPatternCount;
|
|
1400
|
+
lines.push(
|
|
1401
|
+
import_ansis.default.hex("#ff6347")(
|
|
1402
|
+
`${n} noisy pattern${n !== 1 ? "s" : ""} detected (${summary.noisyThreshold}+ issues) \u2014 consider disabling or reconfiguring`
|
|
1403
|
+
)
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
lines.push("");
|
|
1407
|
+
let maxLabelLen = 0;
|
|
1408
|
+
let maxCountLen = 0;
|
|
1409
|
+
for (const group of summary.groups) {
|
|
1410
|
+
const visible = group.patterns.slice(0, MAX_PATTERNS_PER_GROUP);
|
|
1411
|
+
for (const p of visible) {
|
|
1412
|
+
const label = `${p.title} (${p.toolDisplayName})`;
|
|
1413
|
+
maxLabelLen = Math.max(maxLabelLen, label.length);
|
|
1414
|
+
const countStr = `${p.issueCount} issue${p.issueCount !== 1 ? "s" : ""}`;
|
|
1415
|
+
maxCountLen = Math.max(maxCountLen, countStr.length);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
for (const group of summary.groups) {
|
|
1419
|
+
const color = severityColorFn(group.severity);
|
|
1420
|
+
lines.push(color(`${group.severityLabel} \u2014 ${group.categoryLabel}`));
|
|
1421
|
+
const visible = group.patterns.slice(0, MAX_PATTERNS_PER_GROUP);
|
|
1422
|
+
const remaining = group.patterns.length - visible.length;
|
|
1423
|
+
for (const pattern of visible) {
|
|
1424
|
+
const label = `${pattern.title} (${pattern.toolDisplayName})`;
|
|
1425
|
+
const countStr = `${pattern.issueCount} issue${pattern.issueCount !== 1 ? "s" : ""}`;
|
|
1426
|
+
const fileStr = `in ${pattern.fileCount} file${pattern.fileCount !== 1 ? "s" : ""}`;
|
|
1427
|
+
const noisyStr = pattern.noisy ? import_ansis.default.bold.red(" NOISY") : "";
|
|
1428
|
+
lines.push(
|
|
1429
|
+
` ${label.padEnd(maxLabelLen)} ${countStr.padStart(maxCountLen)} ${fileStr}${noisyStr}`
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
if (remaining > 0) {
|
|
1433
|
+
lines.push(import_ansis.default.dim(` ... and ${remaining} other pattern${remaining !== 1 ? "s" : ""}`));
|
|
1434
|
+
}
|
|
1435
|
+
lines.push("");
|
|
1436
|
+
}
|
|
1437
|
+
return lines.join("\n");
|
|
1438
|
+
}
|
|
1244
1439
|
|
|
1245
1440
|
// src/init.ts
|
|
1246
|
-
var
|
|
1247
|
-
var
|
|
1441
|
+
var import_promises4 = __toESM(require("fs/promises"));
|
|
1442
|
+
var import_path7 = __toESM(require("path"));
|
|
1248
1443
|
var import_child_process3 = require("child_process");
|
|
1249
1444
|
var import_tooling5 = require("@codacy/tooling");
|
|
1250
1445
|
|
|
1251
|
-
// src/
|
|
1446
|
+
// src/discover.ts
|
|
1252
1447
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
1253
1448
|
var import_path5 = __toESM(require("path"));
|
|
1449
|
+
|
|
1450
|
+
// src/discover-catalog.ts
|
|
1451
|
+
var DEPENDENCY_CATALOG = /* @__PURE__ */ new Map([
|
|
1452
|
+
// --- JavaScript / TypeScript — Frameworks ---
|
|
1453
|
+
["react", { displayName: "React", kind: "framework" }],
|
|
1454
|
+
["react-dom", { displayName: "React DOM", kind: "framework" }],
|
|
1455
|
+
["react-native", { displayName: "React Native", kind: "framework" }],
|
|
1456
|
+
["vue", { displayName: "Vue.js", kind: "framework" }],
|
|
1457
|
+
["nuxt", { displayName: "Nuxt", kind: "framework" }],
|
|
1458
|
+
["@angular/core", { displayName: "Angular", kind: "framework" }],
|
|
1459
|
+
["svelte", { displayName: "Svelte", kind: "framework" }],
|
|
1460
|
+
["@sveltejs/kit", { displayName: "SvelteKit", kind: "framework" }],
|
|
1461
|
+
["next", { displayName: "Next.js", kind: "framework" }],
|
|
1462
|
+
["ember-source", { displayName: "Ember.js", kind: "framework" }],
|
|
1463
|
+
["lit", { displayName: "Lit", kind: "framework" }],
|
|
1464
|
+
["solid-js", { displayName: "Solid", kind: "framework" }],
|
|
1465
|
+
["astro", { displayName: "Astro", kind: "framework" }],
|
|
1466
|
+
["@builder.io/qwik", { displayName: "Qwik", kind: "framework" }],
|
|
1467
|
+
["@builder.io/qwik-city", { displayName: "Qwik", kind: "framework" }],
|
|
1468
|
+
["@remix-run/react", { displayName: "Remix", kind: "framework" }],
|
|
1469
|
+
["gatsby", { displayName: "Gatsby", kind: "framework" }],
|
|
1470
|
+
["preact", { displayName: "Preact", kind: "framework" }],
|
|
1471
|
+
["express", { displayName: "Express", kind: "framework" }],
|
|
1472
|
+
["@nestjs/core", { displayName: "NestJS", kind: "framework" }],
|
|
1473
|
+
["fastify", { displayName: "Fastify", kind: "framework" }],
|
|
1474
|
+
["koa", { displayName: "Koa", kind: "framework" }],
|
|
1475
|
+
["@hapi/hapi", { displayName: "Hapi", kind: "framework" }],
|
|
1476
|
+
["hono", { displayName: "Hono", kind: "framework" }],
|
|
1477
|
+
["electron", { displayName: "Electron", kind: "framework" }],
|
|
1478
|
+
// --- JavaScript / TypeScript — Libraries ---
|
|
1479
|
+
["lodash", { displayName: "Lodash", kind: "library" }],
|
|
1480
|
+
["underscore", { displayName: "Underscore.js", kind: "library" }],
|
|
1481
|
+
["ramda", { displayName: "Ramda", kind: "library" }],
|
|
1482
|
+
["jest", { displayName: "Jest", kind: "library" }],
|
|
1483
|
+
["vitest", { displayName: "Vitest", kind: "library" }],
|
|
1484
|
+
["@playwright/test", { displayName: "Playwright", kind: "library" }],
|
|
1485
|
+
["playwright", { displayName: "Playwright", kind: "library" }],
|
|
1486
|
+
["cypress", { displayName: "Cypress", kind: "library" }],
|
|
1487
|
+
["mocha", { displayName: "Mocha", kind: "library" }],
|
|
1488
|
+
["ava", { displayName: "AVA", kind: "library" }],
|
|
1489
|
+
["jasmine", { displayName: "Jasmine", kind: "library" }],
|
|
1490
|
+
["jasmine-core", { displayName: "Jasmine", kind: "library" }],
|
|
1491
|
+
["@testing-library/react", { displayName: "Testing Library", kind: "library" }],
|
|
1492
|
+
["@testing-library/vue", { displayName: "Testing Library", kind: "library" }],
|
|
1493
|
+
["@testing-library/dom", { displayName: "Testing Library", kind: "library" }],
|
|
1494
|
+
["tailwindcss", { displayName: "Tailwind CSS", kind: "library" }],
|
|
1495
|
+
["@storybook/react", { displayName: "Storybook", kind: "library" }],
|
|
1496
|
+
["@storybook/vue3", { displayName: "Storybook", kind: "library" }],
|
|
1497
|
+
["@storybook/svelte", { displayName: "Storybook", kind: "library" }],
|
|
1498
|
+
["redux", { displayName: "Redux", kind: "library" }],
|
|
1499
|
+
["@reduxjs/toolkit", { displayName: "Redux Toolkit", kind: "library" }],
|
|
1500
|
+
["mobx", { displayName: "MobX", kind: "library" }],
|
|
1501
|
+
["zustand", { displayName: "Zustand", kind: "library" }],
|
|
1502
|
+
["axios", { displayName: "Axios", kind: "library" }],
|
|
1503
|
+
["date-fns", { displayName: "date-fns", kind: "library" }],
|
|
1504
|
+
["dayjs", { displayName: "Day.js", kind: "library" }],
|
|
1505
|
+
["moment", { displayName: "Moment.js", kind: "library" }],
|
|
1506
|
+
["rxjs", { displayName: "RxJS", kind: "library" }],
|
|
1507
|
+
["zod", { displayName: "Zod", kind: "library" }],
|
|
1508
|
+
["joi", { displayName: "Joi", kind: "library" }],
|
|
1509
|
+
["yup", { displayName: "Yup", kind: "library" }],
|
|
1510
|
+
["prisma", { displayName: "Prisma", kind: "library" }],
|
|
1511
|
+
["@prisma/client", { displayName: "Prisma", kind: "library" }],
|
|
1512
|
+
["typeorm", { displayName: "TypeORM", kind: "library" }],
|
|
1513
|
+
["sequelize", { displayName: "Sequelize", kind: "library" }],
|
|
1514
|
+
["drizzle-orm", { displayName: "Drizzle ORM", kind: "library" }],
|
|
1515
|
+
["mongoose", { displayName: "Mongoose", kind: "library" }],
|
|
1516
|
+
["graphql", { displayName: "GraphQL", kind: "library" }],
|
|
1517
|
+
["@apollo/client", { displayName: "Apollo Client", kind: "library" }],
|
|
1518
|
+
["socket.io", { displayName: "Socket.IO", kind: "library" }],
|
|
1519
|
+
["three", { displayName: "Three.js", kind: "library" }],
|
|
1520
|
+
["d3", { displayName: "D3.js", kind: "library" }],
|
|
1521
|
+
["chart.js", { displayName: "Chart.js", kind: "library" }],
|
|
1522
|
+
["sass", { displayName: "Sass", kind: "library" }],
|
|
1523
|
+
["node-sass", { displayName: "Sass", kind: "library" }],
|
|
1524
|
+
["less", { displayName: "Less", kind: "library" }],
|
|
1525
|
+
["styled-components", { displayName: "styled-components", kind: "library" }],
|
|
1526
|
+
["@emotion/react", { displayName: "Emotion", kind: "library" }],
|
|
1527
|
+
["pino", { displayName: "Pino", kind: "library" }],
|
|
1528
|
+
["winston", { displayName: "Winston", kind: "library" }],
|
|
1529
|
+
["i18next", { displayName: "i18next", kind: "library" }],
|
|
1530
|
+
["react-intl", { displayName: "react-intl", kind: "library" }],
|
|
1531
|
+
["vue-i18n", { displayName: "vue-i18n", kind: "library" }],
|
|
1532
|
+
["next-intl", { displayName: "next-intl", kind: "library" }],
|
|
1533
|
+
// --- JavaScript / TypeScript — Tools ---
|
|
1534
|
+
["typescript", { displayName: "TypeScript", kind: "tool" }],
|
|
1535
|
+
["eslint", { displayName: "ESLint", kind: "tool" }],
|
|
1536
|
+
["prettier", { displayName: "Prettier", kind: "tool" }],
|
|
1537
|
+
["webpack", { displayName: "Webpack", kind: "tool" }],
|
|
1538
|
+
["vite", { displayName: "Vite", kind: "tool" }],
|
|
1539
|
+
["esbuild", { displayName: "esbuild", kind: "tool" }],
|
|
1540
|
+
["rollup", { displayName: "Rollup", kind: "tool" }],
|
|
1541
|
+
["turbo", { displayName: "Turborepo", kind: "tool" }],
|
|
1542
|
+
["tsup", { displayName: "tsup", kind: "tool" }],
|
|
1543
|
+
["@biomejs/biome", { displayName: "Biome", kind: "tool" }],
|
|
1544
|
+
["stylelint", { displayName: "Stylelint", kind: "tool" }],
|
|
1545
|
+
// --- JavaScript / TypeScript — Platforms ---
|
|
1546
|
+
["@lwc/engine-dom", { displayName: "Lightning Web Components", kind: "platform" }],
|
|
1547
|
+
["@salesforce/core", { displayName: "Salesforce", kind: "platform" }],
|
|
1548
|
+
["@shopify/polaris", { displayName: "Shopify Polaris", kind: "platform" }],
|
|
1549
|
+
// --- Python — Frameworks ---
|
|
1550
|
+
["django", { displayName: "Django", kind: "framework" }],
|
|
1551
|
+
["flask", { displayName: "Flask", kind: "framework" }],
|
|
1552
|
+
["fastapi", { displayName: "FastAPI", kind: "framework" }],
|
|
1553
|
+
["tornado", { displayName: "Tornado", kind: "framework" }],
|
|
1554
|
+
["pyramid", { displayName: "Pyramid", kind: "framework" }],
|
|
1555
|
+
["starlette", { displayName: "Starlette", kind: "framework" }],
|
|
1556
|
+
["sanic", { displayName: "Sanic", kind: "framework" }],
|
|
1557
|
+
["bottle", { displayName: "Bottle", kind: "framework" }],
|
|
1558
|
+
["streamlit", { displayName: "Streamlit", kind: "framework" }],
|
|
1559
|
+
["gradio", { displayName: "Gradio", kind: "framework" }],
|
|
1560
|
+
["apache-airflow", { displayName: "Airflow", kind: "framework" }],
|
|
1561
|
+
// --- Python — Libraries ---
|
|
1562
|
+
["flask-babel", { displayName: "Flask-Babel", kind: "library" }],
|
|
1563
|
+
["pytest", { displayName: "pytest", kind: "library" }],
|
|
1564
|
+
["numpy", { displayName: "NumPy", kind: "library" }],
|
|
1565
|
+
["pandas", { displayName: "pandas", kind: "library" }],
|
|
1566
|
+
["requests", { displayName: "Requests", kind: "library" }],
|
|
1567
|
+
["sqlalchemy", { displayName: "SQLAlchemy", kind: "library" }],
|
|
1568
|
+
["celery", { displayName: "Celery", kind: "library" }],
|
|
1569
|
+
["pydantic", { displayName: "Pydantic", kind: "library" }],
|
|
1570
|
+
["boto3", { displayName: "Boto3 (AWS SDK)", kind: "library" }],
|
|
1571
|
+
["scipy", { displayName: "SciPy", kind: "library" }],
|
|
1572
|
+
["scikit-learn", { displayName: "scikit-learn", kind: "library" }],
|
|
1573
|
+
["tensorflow", { displayName: "TensorFlow", kind: "library" }],
|
|
1574
|
+
["torch", { displayName: "PyTorch", kind: "library" }],
|
|
1575
|
+
["httpx", { displayName: "HTTPX", kind: "library" }],
|
|
1576
|
+
["aiohttp", { displayName: "aiohttp", kind: "library" }],
|
|
1577
|
+
["pillow", { displayName: "Pillow", kind: "library" }],
|
|
1578
|
+
["beautifulsoup4", { displayName: "Beautiful Soup", kind: "library" }],
|
|
1579
|
+
["scrapy", { displayName: "Scrapy", kind: "library" }],
|
|
1580
|
+
["alembic", { displayName: "Alembic", kind: "library" }],
|
|
1581
|
+
["marshmallow", { displayName: "Marshmallow", kind: "library" }],
|
|
1582
|
+
["click", { displayName: "Click", kind: "library" }],
|
|
1583
|
+
["typer", { displayName: "Typer", kind: "library" }],
|
|
1584
|
+
["rich", { displayName: "Rich", kind: "library" }],
|
|
1585
|
+
["polars", { displayName: "Polars", kind: "library" }],
|
|
1586
|
+
["dask", { displayName: "Dask", kind: "library" }],
|
|
1587
|
+
["matplotlib", { displayName: "Matplotlib", kind: "library" }],
|
|
1588
|
+
["seaborn", { displayName: "Seaborn", kind: "library" }],
|
|
1589
|
+
["plotly", { displayName: "Plotly", kind: "library" }],
|
|
1590
|
+
// --- Python — Tools ---
|
|
1591
|
+
["black", { displayName: "Black", kind: "tool" }],
|
|
1592
|
+
["ruff", { displayName: "Ruff", kind: "tool" }],
|
|
1593
|
+
["mypy", { displayName: "mypy", kind: "tool" }],
|
|
1594
|
+
["pylint", { displayName: "Pylint", kind: "tool" }],
|
|
1595
|
+
["flake8", { displayName: "Flake8", kind: "tool" }],
|
|
1596
|
+
["bandit", { displayName: "Bandit", kind: "tool" }],
|
|
1597
|
+
["isort", { displayName: "isort", kind: "tool" }],
|
|
1598
|
+
// --- Ruby — Frameworks ---
|
|
1599
|
+
["rails", { displayName: "Ruby on Rails", kind: "framework" }],
|
|
1600
|
+
["sinatra", { displayName: "Sinatra", kind: "framework" }],
|
|
1601
|
+
["hanami", { displayName: "Hanami", kind: "framework" }],
|
|
1602
|
+
["grape", { displayName: "Grape", kind: "framework" }],
|
|
1603
|
+
["padrino", { displayName: "Padrino", kind: "framework" }],
|
|
1604
|
+
// --- Ruby — Libraries ---
|
|
1605
|
+
["rspec", { displayName: "RSpec", kind: "library" }],
|
|
1606
|
+
["rspec-core", { displayName: "RSpec", kind: "library" }],
|
|
1607
|
+
["rspec-rails", { displayName: "RSpec Rails", kind: "library" }],
|
|
1608
|
+
["capybara", { displayName: "Capybara", kind: "library" }],
|
|
1609
|
+
["sidekiq", { displayName: "Sidekiq", kind: "library" }],
|
|
1610
|
+
["devise", { displayName: "Devise", kind: "library" }],
|
|
1611
|
+
["pundit", { displayName: "Pundit", kind: "library" }],
|
|
1612
|
+
["activeadmin", { displayName: "ActiveAdmin", kind: "library" }],
|
|
1613
|
+
["puma", { displayName: "Puma", kind: "library" }],
|
|
1614
|
+
["nokogiri", { displayName: "Nokogiri", kind: "library" }],
|
|
1615
|
+
["faraday", { displayName: "Faraday", kind: "library" }],
|
|
1616
|
+
["httparty", { displayName: "HTTParty", kind: "library" }],
|
|
1617
|
+
["minitest", { displayName: "Minitest", kind: "library" }],
|
|
1618
|
+
["factory_bot", { displayName: "FactoryBot", kind: "library" }],
|
|
1619
|
+
["dry-validation", { displayName: "dry-validation", kind: "library" }],
|
|
1620
|
+
// --- Ruby — Tools ---
|
|
1621
|
+
["rubocop", { displayName: "RuboCop", kind: "tool" }],
|
|
1622
|
+
["bundler", { displayName: "Bundler", kind: "tool" }],
|
|
1623
|
+
["solargraph", { displayName: "Solargraph", kind: "tool" }],
|
|
1624
|
+
// --- Java / Kotlin — Frameworks ---
|
|
1625
|
+
["spring-boot-starter", { displayName: "Spring Boot", kind: "framework" }],
|
|
1626
|
+
["spring-boot-starter-web", { displayName: "Spring Boot", kind: "framework" }],
|
|
1627
|
+
["spring-core", { displayName: "Spring Framework", kind: "framework" }],
|
|
1628
|
+
["quarkus-core", { displayName: "Quarkus", kind: "framework" }],
|
|
1629
|
+
["micronaut-core", { displayName: "Micronaut", kind: "framework" }],
|
|
1630
|
+
["ktor-server-core", { displayName: "Ktor", kind: "framework" }],
|
|
1631
|
+
["android", { displayName: "Android SDK", kind: "framework" }],
|
|
1632
|
+
// --- Java / Kotlin — Libraries ---
|
|
1633
|
+
["junit-jupiter", { displayName: "JUnit 5", kind: "library" }],
|
|
1634
|
+
["junit", { displayName: "JUnit", kind: "library" }],
|
|
1635
|
+
["junit-jupiter-api", { displayName: "JUnit 5", kind: "library" }],
|
|
1636
|
+
["mockito-core", { displayName: "Mockito", kind: "library" }],
|
|
1637
|
+
["lombok", { displayName: "Lombok", kind: "library" }],
|
|
1638
|
+
["jackson-databind", { displayName: "Jackson", kind: "library" }],
|
|
1639
|
+
["jackson-core", { displayName: "Jackson", kind: "library" }],
|
|
1640
|
+
["hibernate-core", { displayName: "Hibernate", kind: "library" }],
|
|
1641
|
+
["guava", { displayName: "Guava", kind: "library" }],
|
|
1642
|
+
["commons-lang3", { displayName: "Apache Commons Lang", kind: "library" }],
|
|
1643
|
+
["commons-io", { displayName: "Apache Commons IO", kind: "library" }],
|
|
1644
|
+
["slf4j-api", { displayName: "SLF4J", kind: "library" }],
|
|
1645
|
+
["log4j-core", { displayName: "Log4j", kind: "library" }],
|
|
1646
|
+
["logback-classic", { displayName: "Logback", kind: "library" }],
|
|
1647
|
+
["testng", { displayName: "TestNG", kind: "library" }],
|
|
1648
|
+
["assertj-core", { displayName: "AssertJ", kind: "library" }],
|
|
1649
|
+
["gson", { displayName: "Gson", kind: "library" }],
|
|
1650
|
+
["okhttp", { displayName: "OkHttp", kind: "library" }],
|
|
1651
|
+
["retrofit", { displayName: "Retrofit", kind: "library" }],
|
|
1652
|
+
// --- Go — Frameworks ---
|
|
1653
|
+
["github.com/gin-gonic/gin", { displayName: "Gin", kind: "framework" }],
|
|
1654
|
+
["github.com/labstack/echo", { displayName: "Echo", kind: "framework" }],
|
|
1655
|
+
["github.com/gofiber/fiber", { displayName: "Fiber", kind: "framework" }],
|
|
1656
|
+
["github.com/go-chi/chi", { displayName: "Chi", kind: "framework" }],
|
|
1657
|
+
["github.com/gorilla/mux", { displayName: "Gorilla Mux", kind: "framework" }],
|
|
1658
|
+
["github.com/beego/beego", { displayName: "Beego", kind: "framework" }],
|
|
1659
|
+
// --- Go — Libraries ---
|
|
1660
|
+
["github.com/stretchr/testify", { displayName: "Testify", kind: "library" }],
|
|
1661
|
+
["github.com/spf13/cobra", { displayName: "Cobra", kind: "library" }],
|
|
1662
|
+
["github.com/spf13/viper", { displayName: "Viper", kind: "library" }],
|
|
1663
|
+
["go.uber.org/zap", { displayName: "Zap", kind: "library" }],
|
|
1664
|
+
["github.com/sirupsen/logrus", { displayName: "Logrus", kind: "library" }],
|
|
1665
|
+
["gorm.io/gorm", { displayName: "GORM", kind: "library" }],
|
|
1666
|
+
["github.com/go-kit/kit", { displayName: "Go Kit", kind: "library" }],
|
|
1667
|
+
["google.golang.org/protobuf", { displayName: "Protocol Buffers", kind: "library" }],
|
|
1668
|
+
["google.golang.org/grpc", { displayName: "gRPC", kind: "library" }],
|
|
1669
|
+
["github.com/jackc/pgx", { displayName: "pgx", kind: "library" }],
|
|
1670
|
+
["github.com/redis/go-redis", { displayName: "go-redis", kind: "library" }],
|
|
1671
|
+
["github.com/aws/aws-sdk-go-v2", { displayName: "AWS SDK for Go", kind: "library" }],
|
|
1672
|
+
["github.com/prometheus/client_golang", { displayName: "Prometheus Client", kind: "library" }],
|
|
1673
|
+
// --- Rust — Frameworks ---
|
|
1674
|
+
["actix-web", { displayName: "Actix Web", kind: "framework" }],
|
|
1675
|
+
["axum", { displayName: "Axum", kind: "framework" }],
|
|
1676
|
+
["rocket", { displayName: "Rocket", kind: "framework" }],
|
|
1677
|
+
["warp", { displayName: "Warp", kind: "framework" }],
|
|
1678
|
+
["tauri", { displayName: "Tauri", kind: "framework" }],
|
|
1679
|
+
// --- Rust — Libraries ---
|
|
1680
|
+
["tokio", { displayName: "Tokio", kind: "library" }],
|
|
1681
|
+
["serde", { displayName: "Serde", kind: "library" }],
|
|
1682
|
+
["clap", { displayName: "clap", kind: "library" }],
|
|
1683
|
+
["reqwest", { displayName: "reqwest", kind: "library" }],
|
|
1684
|
+
["diesel", { displayName: "Diesel", kind: "library" }],
|
|
1685
|
+
["sqlx", { displayName: "SQLx", kind: "library" }],
|
|
1686
|
+
["tracing", { displayName: "Tracing", kind: "library" }],
|
|
1687
|
+
["anyhow", { displayName: "anyhow", kind: "library" }],
|
|
1688
|
+
["thiserror", { displayName: "thiserror", kind: "library" }],
|
|
1689
|
+
["rayon", { displayName: "Rayon", kind: "library" }],
|
|
1690
|
+
// --- PHP — Frameworks ---
|
|
1691
|
+
["laravel/framework", { displayName: "Laravel", kind: "framework" }],
|
|
1692
|
+
["symfony/framework-bundle", { displayName: "Symfony", kind: "framework" }],
|
|
1693
|
+
["codeigniter4/framework", { displayName: "CodeIgniter", kind: "framework" }],
|
|
1694
|
+
["slim/slim", { displayName: "Slim", kind: "framework" }],
|
|
1695
|
+
["cakephp/cakephp", { displayName: "CakePHP", kind: "framework" }],
|
|
1696
|
+
// --- PHP — Libraries ---
|
|
1697
|
+
["phpunit/phpunit", { displayName: "PHPUnit", kind: "library" }],
|
|
1698
|
+
["guzzlehttp/guzzle", { displayName: "Guzzle", kind: "library" }],
|
|
1699
|
+
["monolog/monolog", { displayName: "Monolog", kind: "library" }],
|
|
1700
|
+
["nesbot/carbon", { displayName: "Carbon", kind: "library" }],
|
|
1701
|
+
["doctrine/orm", { displayName: "Doctrine ORM", kind: "library" }],
|
|
1702
|
+
["doctrine/dbal", { displayName: "Doctrine DBAL", kind: "library" }],
|
|
1703
|
+
["league/flysystem", { displayName: "Flysystem", kind: "library" }],
|
|
1704
|
+
["php-amqplib/php-amqplib", { displayName: "php-amqplib", kind: "library" }],
|
|
1705
|
+
["predis/predis", { displayName: "Predis", kind: "library" }],
|
|
1706
|
+
// --- PHP — Tools ---
|
|
1707
|
+
["phpstan/phpstan", { displayName: "PHPStan", kind: "tool" }],
|
|
1708
|
+
["squizlabs/php_codesniffer", { displayName: "PHP_CodeSniffer", kind: "tool" }],
|
|
1709
|
+
// --- Swift — Frameworks ---
|
|
1710
|
+
["vapor", { displayName: "Vapor", kind: "framework" }],
|
|
1711
|
+
// --- Swift — Libraries ---
|
|
1712
|
+
["Alamofire", { displayName: "Alamofire", kind: "library" }],
|
|
1713
|
+
["SnapKit", { displayName: "SnapKit", kind: "library" }],
|
|
1714
|
+
["Kingfisher", { displayName: "Kingfisher", kind: "library" }],
|
|
1715
|
+
["Moya", { displayName: "Moya", kind: "library" }],
|
|
1716
|
+
["RxSwift", { displayName: "RxSwift", kind: "library" }],
|
|
1717
|
+
["RealmSwift", { displayName: "Realm", kind: "library" }],
|
|
1718
|
+
// --- Scala — Frameworks ---
|
|
1719
|
+
["play-server", { displayName: "Play Framework", kind: "framework" }],
|
|
1720
|
+
["akka-actor", { displayName: "Akka", kind: "framework" }],
|
|
1721
|
+
// --- Scala — Libraries ---
|
|
1722
|
+
["scalatest", { displayName: "ScalaTest", kind: "library" }],
|
|
1723
|
+
["specs2-core", { displayName: "Specs2", kind: "library" }],
|
|
1724
|
+
["cats-core", { displayName: "Cats", kind: "library" }],
|
|
1725
|
+
["circe-core", { displayName: "Circe", kind: "library" }]
|
|
1726
|
+
]);
|
|
1727
|
+
var DEPENDENCY_PREFIX_RULES = [
|
|
1728
|
+
{ prefix: "@angular/", classification: { displayName: "Angular", kind: "framework" } },
|
|
1729
|
+
{ prefix: "@nestjs/", classification: { displayName: "NestJS", kind: "framework" } },
|
|
1730
|
+
{ prefix: "@remix-run/", classification: { displayName: "Remix", kind: "framework" } },
|
|
1731
|
+
{ prefix: "@sveltejs/", classification: { displayName: "SvelteKit", kind: "framework" } },
|
|
1732
|
+
{ prefix: "@nuxt/", classification: { displayName: "Nuxt", kind: "framework" } },
|
|
1733
|
+
{ prefix: "@storybook/", classification: { displayName: "Storybook", kind: "library" } },
|
|
1734
|
+
{
|
|
1735
|
+
prefix: "@testing-library/",
|
|
1736
|
+
classification: { displayName: "Testing Library", kind: "library" }
|
|
1737
|
+
},
|
|
1738
|
+
{ prefix: "@tanstack/", classification: { displayName: "TanStack", kind: "library" } },
|
|
1739
|
+
{ prefix: "@reduxjs/", classification: { displayName: "Redux", kind: "library" } },
|
|
1740
|
+
{ prefix: "@prisma/", classification: { displayName: "Prisma", kind: "library" } },
|
|
1741
|
+
{ prefix: "@apollo/", classification: { displayName: "Apollo", kind: "library" } },
|
|
1742
|
+
{ prefix: "@formatjs/", classification: { displayName: "react-intl", kind: "library" } },
|
|
1743
|
+
{ prefix: "@lingui/", classification: { displayName: "Lingui", kind: "library" } },
|
|
1744
|
+
{ prefix: "@emotion/", classification: { displayName: "Emotion", kind: "library" } },
|
|
1745
|
+
{ prefix: "@mui/", classification: { displayName: "Material UI", kind: "library" } },
|
|
1746
|
+
{ prefix: "@chakra-ui/", classification: { displayName: "Chakra UI", kind: "library" } },
|
|
1747
|
+
{
|
|
1748
|
+
prefix: "@lwc/",
|
|
1749
|
+
classification: { displayName: "Lightning Web Components", kind: "platform" }
|
|
1750
|
+
},
|
|
1751
|
+
{ prefix: "@salesforce/", classification: { displayName: "Salesforce", kind: "platform" } },
|
|
1752
|
+
{ prefix: "@shopify/", classification: { displayName: "Shopify", kind: "platform" } },
|
|
1753
|
+
{ prefix: "@aws-sdk/", classification: { displayName: "AWS SDK", kind: "library" } },
|
|
1754
|
+
{ prefix: "@google-cloud/", classification: { displayName: "Google Cloud", kind: "library" } },
|
|
1755
|
+
{ prefix: "@azure/", classification: { displayName: "Azure SDK", kind: "library" } }
|
|
1756
|
+
];
|
|
1757
|
+
function classifyDependency(name) {
|
|
1758
|
+
const exact = DEPENDENCY_CATALOG.get(name);
|
|
1759
|
+
if (exact) return exact;
|
|
1760
|
+
for (const rule of DEPENDENCY_PREFIX_RULES) {
|
|
1761
|
+
if (name.startsWith(rule.prefix)) return rule.classification;
|
|
1762
|
+
}
|
|
1763
|
+
return void 0;
|
|
1764
|
+
}
|
|
1765
|
+
var NOTABLE_ANY_DEPTH = /* @__PURE__ */ new Set([
|
|
1766
|
+
"Dockerfile",
|
|
1767
|
+
"docker-compose.yml",
|
|
1768
|
+
"docker-compose.yaml",
|
|
1769
|
+
"compose.yml",
|
|
1770
|
+
"compose.yaml",
|
|
1771
|
+
"Makefile",
|
|
1772
|
+
"Justfile",
|
|
1773
|
+
"pom.xml",
|
|
1774
|
+
"build.gradle",
|
|
1775
|
+
"build.gradle.kts",
|
|
1776
|
+
"build.sbt",
|
|
1777
|
+
"go.mod",
|
|
1778
|
+
"Cargo.toml",
|
|
1779
|
+
"Gemfile",
|
|
1780
|
+
"Podfile",
|
|
1781
|
+
"Package.swift",
|
|
1782
|
+
"Jenkinsfile",
|
|
1783
|
+
"Vagrantfile",
|
|
1784
|
+
"Procfile"
|
|
1785
|
+
]);
|
|
1786
|
+
var NOTABLE_ROOT_ONLY = /* @__PURE__ */ new Set([
|
|
1787
|
+
".dockerignore",
|
|
1788
|
+
"Taskfile.yml",
|
|
1789
|
+
"Rakefile",
|
|
1790
|
+
"Gruntfile.js",
|
|
1791
|
+
"Gulpfile.js",
|
|
1792
|
+
"settings.gradle",
|
|
1793
|
+
"settings.gradle.kts",
|
|
1794
|
+
"go.sum",
|
|
1795
|
+
"Cargo.lock",
|
|
1796
|
+
"CLAUDE.md",
|
|
1797
|
+
"AGENTS.md",
|
|
1798
|
+
"agents.md",
|
|
1799
|
+
".cursorrules",
|
|
1800
|
+
"copilot-instructions.md",
|
|
1801
|
+
".travis.yml",
|
|
1802
|
+
".gitlab-ci.yml",
|
|
1803
|
+
"azure-pipelines.yml",
|
|
1804
|
+
"bitbucket-pipelines.yml",
|
|
1805
|
+
"appveyor.yml",
|
|
1806
|
+
"package.json",
|
|
1807
|
+
"requirements.txt",
|
|
1808
|
+
"pyproject.toml",
|
|
1809
|
+
"Pipfile",
|
|
1810
|
+
"composer.json",
|
|
1811
|
+
"tsconfig.json",
|
|
1812
|
+
"jsconfig.json",
|
|
1813
|
+
"serverless.yml",
|
|
1814
|
+
"serverless.yaml",
|
|
1815
|
+
"cdk.json",
|
|
1816
|
+
"pulumi.yaml",
|
|
1817
|
+
"README.md",
|
|
1818
|
+
"CHANGELOG.md",
|
|
1819
|
+
"CONTRIBUTING.md",
|
|
1820
|
+
"LICENSE",
|
|
1821
|
+
"renovate.json",
|
|
1822
|
+
".nvmrc",
|
|
1823
|
+
".node-version",
|
|
1824
|
+
".python-version",
|
|
1825
|
+
".ruby-version",
|
|
1826
|
+
".tool-versions"
|
|
1827
|
+
]);
|
|
1828
|
+
var NOTABLE_PATH_PREFIXES = [".github/workflows/", ".circleci/", ".gitlab/"];
|
|
1829
|
+
var CONFIG_HEURISTIC_PATTERNS = [
|
|
1830
|
+
/^\..*rc$/,
|
|
1831
|
+
// .eslintrc, .prettierrc, etc.
|
|
1832
|
+
/^\..*rc\.(json|js|cjs|mjs|yml|yaml|ts)$/,
|
|
1833
|
+
// .eslintrc.json, etc.
|
|
1834
|
+
/^.*\.config\.(js|ts|mjs|cjs)$/,
|
|
1835
|
+
// vite.config.ts, jest.config.js, etc.
|
|
1836
|
+
/^\.env(\..+)?$/
|
|
1837
|
+
// .env, .env.local, .env.production
|
|
1838
|
+
];
|
|
1839
|
+
function isNotableFile(filePath) {
|
|
1840
|
+
const basename = filePath.split("/").pop() ?? filePath;
|
|
1841
|
+
const isRoot = !filePath.includes("/");
|
|
1842
|
+
if (NOTABLE_ANY_DEPTH.has(basename)) return true;
|
|
1843
|
+
if (isRoot && NOTABLE_ROOT_ONLY.has(basename)) return true;
|
|
1844
|
+
for (const prefix of NOTABLE_PATH_PREFIXES) {
|
|
1845
|
+
if (filePath.startsWith(prefix)) return true;
|
|
1846
|
+
}
|
|
1847
|
+
if (!filePath.includes("/")) {
|
|
1848
|
+
for (const pattern of CONFIG_HEURISTIC_PATTERNS) {
|
|
1849
|
+
if (pattern.test(basename)) return true;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
return false;
|
|
1853
|
+
}
|
|
1854
|
+
function parsePackageJson(content) {
|
|
1855
|
+
try {
|
|
1856
|
+
const pkg = JSON.parse(content);
|
|
1857
|
+
const deps = [];
|
|
1858
|
+
for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
|
|
1859
|
+
const entries2 = pkg[section];
|
|
1860
|
+
if (entries2 && typeof entries2 === "object") {
|
|
1861
|
+
for (const [name, version] of Object.entries(entries2)) {
|
|
1862
|
+
deps.push({ name, version: typeof version === "string" ? version : void 0 });
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
return deps;
|
|
1867
|
+
} catch {
|
|
1868
|
+
return [];
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
function parseRequirementsTxt(content) {
|
|
1872
|
+
const deps = [];
|
|
1873
|
+
for (const rawLine of content.split("\n")) {
|
|
1874
|
+
const line = rawLine.trim();
|
|
1875
|
+
if (!line || line.startsWith("#") || line.startsWith("-")) continue;
|
|
1876
|
+
const noComment = line.split("#")[0].trim();
|
|
1877
|
+
if (!noComment) continue;
|
|
1878
|
+
const match = noComment.match(/^([a-zA-Z0-9_.-]+(?:\[[^\]]*\])?)\s*([<>=!~@;].*)?$/);
|
|
1879
|
+
if (match) {
|
|
1880
|
+
const rawName = match[1].replace(/\[.*\]$/, "");
|
|
1881
|
+
const normalized = rawName.toLowerCase().replace(/_/g, "-");
|
|
1882
|
+
deps.push({ name: normalized, version: match[2]?.trim() });
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
return deps;
|
|
1886
|
+
}
|
|
1887
|
+
function parsePyprojectToml(content) {
|
|
1888
|
+
const deps = [];
|
|
1889
|
+
const projectDepsMatch = content.match(/\[project\][\s\S]*?dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
1890
|
+
if (projectDepsMatch) {
|
|
1891
|
+
const items = projectDepsMatch[1].match(/"([^"]+)"|'([^']+)'/g) ?? [];
|
|
1892
|
+
for (const item of items) {
|
|
1893
|
+
const raw = item.replace(/["']/g, "");
|
|
1894
|
+
const name = raw.split(/[<>=!~;\s]/)[0].replace(/\[.*\]$/, "");
|
|
1895
|
+
if (name) deps.push({ name: name.toLowerCase().replace(/_/g, "-") });
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
const poetryMatch = content.match(/\[tool\.poetry\.dependencies\]([\s\S]*?)(?:\n\[|\n$)/);
|
|
1899
|
+
if (poetryMatch) {
|
|
1900
|
+
const lines = poetryMatch[1].split("\n");
|
|
1901
|
+
for (const line of lines) {
|
|
1902
|
+
const m = line.match(/^([a-zA-Z0-9_.-]+)\s*=/);
|
|
1903
|
+
if (m && m[1] !== "python") {
|
|
1904
|
+
deps.push({ name: m[1].toLowerCase().replace(/_/g, "-") });
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
const poetryGroupRegex = /\[tool\.poetry\.group\.\w+\.dependencies\]([\s\S]*?)(?:\n\[|\n$)/g;
|
|
1909
|
+
let groupMatch;
|
|
1910
|
+
while ((groupMatch = poetryGroupRegex.exec(content)) !== null) {
|
|
1911
|
+
const lines = groupMatch[1].split("\n");
|
|
1912
|
+
for (const line of lines) {
|
|
1913
|
+
const m = line.match(/^([a-zA-Z0-9_.-]+)\s*=/);
|
|
1914
|
+
if (m) {
|
|
1915
|
+
deps.push({ name: m[1].toLowerCase().replace(/_/g, "-") });
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return deps;
|
|
1920
|
+
}
|
|
1921
|
+
function parsePipfile(content) {
|
|
1922
|
+
const deps = [];
|
|
1923
|
+
let inDepsSection = false;
|
|
1924
|
+
for (const rawLine of content.split("\n")) {
|
|
1925
|
+
const line = rawLine.trim();
|
|
1926
|
+
if (/^\[(packages|dev-packages)\]/.test(line)) {
|
|
1927
|
+
inDepsSection = true;
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
if (line.startsWith("[")) {
|
|
1931
|
+
inDepsSection = false;
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1934
|
+
if (inDepsSection) {
|
|
1935
|
+
const m = line.match(/^([a-zA-Z0-9_.-]+)\s*=/);
|
|
1936
|
+
if (m) {
|
|
1937
|
+
deps.push({ name: m[1].toLowerCase().replace(/_/g, "-") });
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return deps;
|
|
1942
|
+
}
|
|
1943
|
+
function parseGemfile(content) {
|
|
1944
|
+
const deps = [];
|
|
1945
|
+
const gemRegex = /^\s*gem\s+["']([^"']+)["'](?:\s*,\s*["']([^"']+)["'])?/gm;
|
|
1946
|
+
let match;
|
|
1947
|
+
while ((match = gemRegex.exec(content)) !== null) {
|
|
1948
|
+
deps.push({ name: match[1], version: match[2] });
|
|
1949
|
+
}
|
|
1950
|
+
return deps;
|
|
1951
|
+
}
|
|
1952
|
+
function parseGoMod(content) {
|
|
1953
|
+
const deps = [];
|
|
1954
|
+
const singleRegex = /^require\s+(\S+)\s+(\S+)/gm;
|
|
1955
|
+
let match;
|
|
1956
|
+
while ((match = singleRegex.exec(content)) !== null) {
|
|
1957
|
+
if (!match[1].startsWith("(")) {
|
|
1958
|
+
deps.push({ name: match[1], version: match[2] });
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
const blockRegex = /require\s*\(([\s\S]*?)\)/g;
|
|
1962
|
+
while ((match = blockRegex.exec(content)) !== null) {
|
|
1963
|
+
const lines = match[1].split("\n");
|
|
1964
|
+
for (const line of lines) {
|
|
1965
|
+
const m = line.trim().match(/^(\S+)\s+(\S+)/);
|
|
1966
|
+
if (m && !m[1].startsWith("//")) {
|
|
1967
|
+
deps.push({ name: m[1], version: m[2] });
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
return deps;
|
|
1972
|
+
}
|
|
1973
|
+
function parsePomXml(content) {
|
|
1974
|
+
const deps = [];
|
|
1975
|
+
const depRegex = /<dependency>[\s\S]*?<artifactId>([^<]+)<\/artifactId>[\s\S]*?<\/dependency>/g;
|
|
1976
|
+
let match;
|
|
1977
|
+
while ((match = depRegex.exec(content)) !== null) {
|
|
1978
|
+
deps.push({ name: match[1].trim() });
|
|
1979
|
+
}
|
|
1980
|
+
return deps;
|
|
1981
|
+
}
|
|
1982
|
+
function parseBuildGradle(content) {
|
|
1983
|
+
const deps = [];
|
|
1984
|
+
const depRegex = /(?:implementation|testImplementation|api|compileOnly|runtimeOnly|kapt|annotationProcessor)\s*(?:\(\s*)?["']([^"':]+):([^"':]+)(?::([^"']+))?["']/g;
|
|
1985
|
+
let match;
|
|
1986
|
+
while ((match = depRegex.exec(content)) !== null) {
|
|
1987
|
+
deps.push({ name: match[2].trim(), version: match[3]?.trim() });
|
|
1988
|
+
}
|
|
1989
|
+
return deps;
|
|
1990
|
+
}
|
|
1991
|
+
function parseCargoToml(content) {
|
|
1992
|
+
const deps = [];
|
|
1993
|
+
let inDepsSection = false;
|
|
1994
|
+
for (const rawLine of content.split("\n")) {
|
|
1995
|
+
const line = rawLine.trim();
|
|
1996
|
+
if (/^\[((?:dev-|build-)?dependencies)\]/.test(line)) {
|
|
1997
|
+
inDepsSection = true;
|
|
1998
|
+
continue;
|
|
1999
|
+
}
|
|
2000
|
+
if (line.startsWith("[") && !line.includes("dependencies.")) {
|
|
2001
|
+
inDepsSection = false;
|
|
2002
|
+
continue;
|
|
2003
|
+
}
|
|
2004
|
+
if (inDepsSection) {
|
|
2005
|
+
const m = line.match(/^([a-zA-Z0-9_-]+)\s*=/);
|
|
2006
|
+
if (m) {
|
|
2007
|
+
const versionMatch = line.match(/["']([^"']+)["']/);
|
|
2008
|
+
deps.push({ name: m[1], version: versionMatch?.[1] });
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
return deps;
|
|
2013
|
+
}
|
|
2014
|
+
function parseComposerJson(content) {
|
|
2015
|
+
try {
|
|
2016
|
+
const pkg = JSON.parse(content);
|
|
2017
|
+
const deps = [];
|
|
2018
|
+
for (const section of ["require", "require-dev"]) {
|
|
2019
|
+
const entries2 = pkg[section];
|
|
2020
|
+
if (entries2 && typeof entries2 === "object") {
|
|
2021
|
+
for (const [name, version] of Object.entries(entries2)) {
|
|
2022
|
+
if (name === "php" || name.startsWith("ext-")) continue;
|
|
2023
|
+
deps.push({ name, version: typeof version === "string" ? version : void 0 });
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
return deps;
|
|
2028
|
+
} catch {
|
|
2029
|
+
return [];
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
function parsePodfile(content) {
|
|
2033
|
+
const deps = [];
|
|
2034
|
+
const podRegex = /^\s*pod\s+["']([^"']+)["'](?:\s*,\s*["']([^"']+)["'])?/gm;
|
|
2035
|
+
let match;
|
|
2036
|
+
while ((match = podRegex.exec(content)) !== null) {
|
|
2037
|
+
deps.push({ name: match[1], version: match[2] });
|
|
2038
|
+
}
|
|
2039
|
+
return deps;
|
|
2040
|
+
}
|
|
2041
|
+
function parsePackageSwift(content) {
|
|
2042
|
+
const deps = [];
|
|
2043
|
+
const pkgRegex = /\.package\s*\(\s*url:\s*["'](?:https?:\/\/[^/]+\/[^/]+\/|git@[^:]+:[^/]+\/)([^"'/.]+)/g;
|
|
2044
|
+
let match;
|
|
2045
|
+
while ((match = pkgRegex.exec(content)) !== null) {
|
|
2046
|
+
deps.push({ name: match[1] });
|
|
2047
|
+
}
|
|
2048
|
+
return deps;
|
|
2049
|
+
}
|
|
2050
|
+
var MANIFEST_PARSERS = /* @__PURE__ */ new Map([
|
|
2051
|
+
["package.json", parsePackageJson],
|
|
2052
|
+
["requirements.txt", parseRequirementsTxt],
|
|
2053
|
+
["pyproject.toml", parsePyprojectToml],
|
|
2054
|
+
["Pipfile", parsePipfile],
|
|
2055
|
+
["Gemfile", parseGemfile],
|
|
2056
|
+
["go.mod", parseGoMod],
|
|
2057
|
+
["pom.xml", parsePomXml],
|
|
2058
|
+
["build.gradle", parseBuildGradle],
|
|
2059
|
+
["build.gradle.kts", parseBuildGradle],
|
|
2060
|
+
["Cargo.toml", parseCargoToml],
|
|
2061
|
+
["composer.json", parseComposerJson],
|
|
2062
|
+
["Podfile", parsePodfile],
|
|
2063
|
+
["Package.swift", parsePackageSwift]
|
|
2064
|
+
]);
|
|
2065
|
+
|
|
2066
|
+
// src/discover.ts
|
|
2067
|
+
async function discover(repositoryRoot, options) {
|
|
2068
|
+
const files = listRepoFiles(repositoryRoot);
|
|
2069
|
+
const filePatterns = extractFilePatterns(files);
|
|
2070
|
+
const notableFiles = findNotableFiles(files);
|
|
2071
|
+
const languages = await detectLanguages(repositoryRoot, files);
|
|
2072
|
+
let frameworks = [];
|
|
2073
|
+
let libraries = [];
|
|
2074
|
+
if (!options?.skipDependencies) {
|
|
2075
|
+
const allDeps = await extractDependencies(repositoryRoot, files);
|
|
2076
|
+
frameworks = deduplicateDeps(allDeps.filter((d) => d.kind === "framework"));
|
|
2077
|
+
libraries = deduplicateDeps(
|
|
2078
|
+
allDeps.filter((d) => d.kind === "library" || d.kind === "platform" || d.kind === "tool")
|
|
2079
|
+
);
|
|
2080
|
+
}
|
|
2081
|
+
return {
|
|
2082
|
+
filePatterns,
|
|
2083
|
+
notableFiles,
|
|
2084
|
+
languages,
|
|
2085
|
+
frameworks,
|
|
2086
|
+
libraries,
|
|
2087
|
+
metadata: {
|
|
2088
|
+
repositoryRoot: import_path5.default.resolve(repositoryRoot),
|
|
2089
|
+
totalFiles: files.length,
|
|
2090
|
+
scannedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2091
|
+
}
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
function extractFilePatterns(files) {
|
|
2095
|
+
const extensions = /* @__PURE__ */ new Set();
|
|
2096
|
+
for (const file of files) {
|
|
2097
|
+
const ext = import_path5.default.extname(file).toLowerCase();
|
|
2098
|
+
if (ext) {
|
|
2099
|
+
extensions.add(`*${ext}`);
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
return Array.from(extensions).sort();
|
|
2103
|
+
}
|
|
2104
|
+
function findNotableFiles(files) {
|
|
2105
|
+
const notable = /* @__PURE__ */ new Set();
|
|
2106
|
+
for (const file of files) {
|
|
2107
|
+
if (isNotableFile(file)) {
|
|
2108
|
+
notable.add(file);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
return Array.from(notable).sort();
|
|
2112
|
+
}
|
|
2113
|
+
async function extractDependencies(repositoryRoot, files) {
|
|
2114
|
+
const manifestFiles = /* @__PURE__ */ new Map();
|
|
2115
|
+
for (const file of files) {
|
|
2116
|
+
const basename = file.split("/").pop() ?? file;
|
|
2117
|
+
if (MANIFEST_PARSERS.has(basename)) {
|
|
2118
|
+
const existing = manifestFiles.get(basename) ?? [];
|
|
2119
|
+
existing.push(file);
|
|
2120
|
+
manifestFiles.set(basename, existing);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
const allDeps = [];
|
|
2124
|
+
for (const [manifestName, paths] of manifestFiles) {
|
|
2125
|
+
const parser = MANIFEST_PARSERS.get(manifestName);
|
|
2126
|
+
for (const filePath of paths) {
|
|
2127
|
+
let content;
|
|
2128
|
+
try {
|
|
2129
|
+
content = await import_promises2.default.readFile(import_path5.default.join(repositoryRoot, filePath), "utf-8");
|
|
2130
|
+
} catch {
|
|
2131
|
+
continue;
|
|
2132
|
+
}
|
|
2133
|
+
const rawDeps = parser(content);
|
|
2134
|
+
for (const raw of rawDeps) {
|
|
2135
|
+
const classification = classifyDependency(raw.name);
|
|
2136
|
+
if (classification) {
|
|
2137
|
+
allDeps.push({
|
|
2138
|
+
name: raw.name,
|
|
2139
|
+
displayName: classification.displayName,
|
|
2140
|
+
kind: classification.kind,
|
|
2141
|
+
source: "manifest",
|
|
2142
|
+
manifestFile: filePath,
|
|
2143
|
+
version: raw.version
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
return allDeps;
|
|
2150
|
+
}
|
|
2151
|
+
function deduplicateDeps(deps) {
|
|
2152
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2153
|
+
const result = [];
|
|
2154
|
+
for (const dep of deps) {
|
|
2155
|
+
if (!seen.has(dep.displayName)) {
|
|
2156
|
+
seen.add(dep.displayName);
|
|
2157
|
+
result.push(dep);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
return result.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
// src/codacy-yaml.ts
|
|
2164
|
+
var import_promises3 = __toESM(require("fs/promises"));
|
|
2165
|
+
var import_path6 = __toESM(require("path"));
|
|
1254
2166
|
var import_yaml = require("yaml");
|
|
1255
2167
|
async function readCodacyYaml(repositoryRoot) {
|
|
1256
2168
|
const candidates = [".codacy.yaml", ".codacy.yml"];
|
|
1257
2169
|
let raw = null;
|
|
1258
2170
|
for (const filename of candidates) {
|
|
1259
2171
|
try {
|
|
1260
|
-
raw = await
|
|
2172
|
+
raw = await import_promises3.default.readFile(import_path6.default.join(repositoryRoot, filename), "utf-8");
|
|
1261
2173
|
break;
|
|
1262
2174
|
} catch {
|
|
1263
2175
|
}
|
|
@@ -1515,13 +2427,13 @@ var getQueryString = (params) => {
|
|
|
1515
2427
|
};
|
|
1516
2428
|
var getUrl = (config, options) => {
|
|
1517
2429
|
const encoder = config.ENCODE_PATH || encodeURI;
|
|
1518
|
-
const
|
|
2430
|
+
const path9 = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => {
|
|
1519
2431
|
if (options.path?.hasOwnProperty(group)) {
|
|
1520
2432
|
return encoder(String(options.path[group]));
|
|
1521
2433
|
}
|
|
1522
2434
|
return substring;
|
|
1523
2435
|
});
|
|
1524
|
-
const url = `${config.BASE}${
|
|
2436
|
+
const url = `${config.BASE}${path9}`;
|
|
1525
2437
|
if (options.query) {
|
|
1526
2438
|
return `${url}${getQueryString(options.query)}`;
|
|
1527
2439
|
}
|
|
@@ -4865,22 +5777,26 @@ async function listIgnoredFiles(provider, org, repo) {
|
|
|
4865
5777
|
}
|
|
4866
5778
|
|
|
4867
5779
|
// src/init.ts
|
|
4868
|
-
async function detectLanguages(repositoryRoot) {
|
|
4869
|
-
let files
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
5780
|
+
async function detectLanguages(repositoryRoot, precomputedFiles) {
|
|
5781
|
+
let files;
|
|
5782
|
+
if (precomputedFiles) {
|
|
5783
|
+
files = precomputedFiles;
|
|
5784
|
+
} else {
|
|
5785
|
+
try {
|
|
5786
|
+
const output = (0, import_child_process3.execSync)("git ls-files", {
|
|
5787
|
+
cwd: repositoryRoot,
|
|
5788
|
+
encoding: "utf-8",
|
|
5789
|
+
maxBuffer: 50 * 1024 * 1024
|
|
5790
|
+
}).trim();
|
|
5791
|
+
files = output ? output.split("\n") : [];
|
|
5792
|
+
} catch {
|
|
5793
|
+
return [];
|
|
5794
|
+
}
|
|
4879
5795
|
}
|
|
4880
5796
|
const detected = /* @__PURE__ */ new Set();
|
|
4881
5797
|
for (const file of files) {
|
|
4882
|
-
const basename =
|
|
4883
|
-
const ext =
|
|
5798
|
+
const basename = import_path7.default.basename(file);
|
|
5799
|
+
const ext = import_path7.default.extname(file).toLowerCase();
|
|
4884
5800
|
for (const [lang, config] of Object.entries(import_tooling5.LANGUAGE_CONFIG)) {
|
|
4885
5801
|
if (config.extensions.includes(ext)) {
|
|
4886
5802
|
detected.add(lang);
|
|
@@ -4897,9 +5813,9 @@ async function detectLocalConfigFiles(repositoryRoot, adapters) {
|
|
|
4897
5813
|
adapters.map(async (adapter) => {
|
|
4898
5814
|
const result = await adapter.checkLocalConfigurationFile({
|
|
4899
5815
|
repositoryRoot,
|
|
4900
|
-
generatedConfigDir:
|
|
4901
|
-
globalDir:
|
|
4902
|
-
toolInstallDir:
|
|
5816
|
+
generatedConfigDir: import_path7.default.join(repositoryRoot, ".codacy", "generated"),
|
|
5817
|
+
globalDir: import_path7.default.join(process.env.HOME ?? "~", ".codacy"),
|
|
5818
|
+
toolInstallDir: import_path7.default.join(process.env.HOME ?? "~", ".codacy", "tools", adapter.id),
|
|
4903
5819
|
targetFiles: [],
|
|
4904
5820
|
platform: { os: process.platform, arch: process.arch },
|
|
4905
5821
|
logger: silentLogger,
|
|
@@ -5096,10 +6012,10 @@ async function initRemoteConfig(repositoryRoot, provider, organization, reposito
|
|
|
5096
6012
|
};
|
|
5097
6013
|
}
|
|
5098
6014
|
async function initContainerConfig(repositoryRoot, adapters) {
|
|
5099
|
-
const codacyrcPath =
|
|
6015
|
+
const codacyrcPath = import_path7.default.join(repositoryRoot, ".codacyrc");
|
|
5100
6016
|
let raw;
|
|
5101
6017
|
try {
|
|
5102
|
-
raw = await
|
|
6018
|
+
raw = await import_promises4.default.readFile(codacyrcPath, "utf-8");
|
|
5103
6019
|
} catch {
|
|
5104
6020
|
throw new Error(`.codacyrc not found at ${codacyrcPath}`);
|
|
5105
6021
|
}
|
|
@@ -5150,10 +6066,257 @@ async function initContainerConfig(repositoryRoot, adapters) {
|
|
|
5150
6066
|
}
|
|
5151
6067
|
return createCodacyConfig({ source: "container", tools, includeFiles });
|
|
5152
6068
|
}
|
|
6069
|
+
async function initAutoConfig(repositoryRoot, adapters, descriptors, filters, onDiscoveryComplete, rawFilterString) {
|
|
6070
|
+
const discoveryResult = await discover(repositoryRoot);
|
|
6071
|
+
onDiscoveryComplete?.(discoveryResult);
|
|
6072
|
+
const detectedKeys = /* @__PURE__ */ new Set();
|
|
6073
|
+
for (const lang of discoveryResult.languages) detectedKeys.add(lang);
|
|
6074
|
+
for (const fw of discoveryResult.frameworks) detectedKeys.add(fw.displayName);
|
|
6075
|
+
for (const lib of discoveryResult.libraries) detectedKeys.add(lib.displayName);
|
|
6076
|
+
const repoLanguages = new Set(discoveryResult.languages);
|
|
6077
|
+
const localConfigs = await detectLocalConfigFiles(repositoryRoot, adapters);
|
|
6078
|
+
const descriptorMap = new Map(descriptors.map((d) => [d.id, d]));
|
|
6079
|
+
const candidates = [];
|
|
6080
|
+
for (const adapter of adapters) {
|
|
6081
|
+
if (!adapter.languages.includes("*") && adapter.languages.length > 0 && repoLanguages.size > 0) {
|
|
6082
|
+
const hasOverlap = adapter.languages.some((lang) => repoLanguages.has(lang));
|
|
6083
|
+
if (!hasOverlap) continue;
|
|
6084
|
+
}
|
|
6085
|
+
candidates.push(adapter);
|
|
6086
|
+
}
|
|
6087
|
+
const deduped = deduplicateToolFamilies(candidates, localConfigs);
|
|
6088
|
+
const tools = [];
|
|
6089
|
+
for (const adapter of deduped) {
|
|
6090
|
+
const localConfigPath = localConfigs.get(adapter.id);
|
|
6091
|
+
if (localConfigPath) {
|
|
6092
|
+
tools.push({
|
|
6093
|
+
toolId: adapter.id,
|
|
6094
|
+
localConfigurationFile: localConfigPath,
|
|
6095
|
+
useLocalConfigurationFile: true,
|
|
6096
|
+
patterns: []
|
|
6097
|
+
});
|
|
6098
|
+
continue;
|
|
6099
|
+
}
|
|
6100
|
+
const patternsMetadata = adapter.patternsMetadata;
|
|
6101
|
+
if (!patternsMetadata || patternsMetadata.length === 0) continue;
|
|
6102
|
+
const desc = descriptorMap.get(adapter.id);
|
|
6103
|
+
const mappings = desc?.frameworkMappings;
|
|
6104
|
+
const selectedPatterns = filterAutoPatterns(
|
|
6105
|
+
patternsMetadata,
|
|
6106
|
+
mappings,
|
|
6107
|
+
detectedKeys,
|
|
6108
|
+
repoLanguages,
|
|
6109
|
+
filters
|
|
6110
|
+
);
|
|
6111
|
+
if (selectedPatterns.length > 0) {
|
|
6112
|
+
tools.push({
|
|
6113
|
+
toolId: adapter.id,
|
|
6114
|
+
patterns: selectedPatterns.map((p) => ({ patternId: p.id }))
|
|
6115
|
+
});
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
const baseConfig = createCodacyConfig({
|
|
6119
|
+
source: "auto",
|
|
6120
|
+
languages: discoveryResult.languages,
|
|
6121
|
+
tools,
|
|
6122
|
+
autoFilters: rawFilterString || void 0
|
|
6123
|
+
});
|
|
6124
|
+
const { config, codacyYamlApplied } = await enrichWithCodacyYaml(
|
|
6125
|
+
baseConfig,
|
|
6126
|
+
repositoryRoot,
|
|
6127
|
+
adapters
|
|
6128
|
+
);
|
|
6129
|
+
return {
|
|
6130
|
+
config,
|
|
6131
|
+
stats: {
|
|
6132
|
+
detectedLanguages: discoveryResult.languages.length,
|
|
6133
|
+
detectedFrameworks: discoveryResult.frameworks.length,
|
|
6134
|
+
detectedLibraries: discoveryResult.libraries.length,
|
|
6135
|
+
selectedTools: tools.length,
|
|
6136
|
+
codacyYamlApplied
|
|
6137
|
+
}
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
function toolFamily(id) {
|
|
6141
|
+
return id.replace(/\d+$/, "");
|
|
6142
|
+
}
|
|
6143
|
+
function deduplicateToolFamilies(candidates, localConfigs) {
|
|
6144
|
+
const families = /* @__PURE__ */ new Map();
|
|
6145
|
+
for (const adapter of candidates) {
|
|
6146
|
+
const family = toolFamily(adapter.id);
|
|
6147
|
+
const group = families.get(family) ?? [];
|
|
6148
|
+
group.push(adapter);
|
|
6149
|
+
families.set(family, group);
|
|
6150
|
+
}
|
|
6151
|
+
const result = [];
|
|
6152
|
+
for (const group of families.values()) {
|
|
6153
|
+
if (group.length === 1) {
|
|
6154
|
+
result.push(group[0]);
|
|
6155
|
+
continue;
|
|
6156
|
+
}
|
|
6157
|
+
const withConfig = group.filter((a) => localConfigs.has(a.id));
|
|
6158
|
+
if (withConfig.length === 1) {
|
|
6159
|
+
result.push(withConfig[0]);
|
|
6160
|
+
continue;
|
|
6161
|
+
}
|
|
6162
|
+
group.sort((a, b) => {
|
|
6163
|
+
const majorA = parseInt(a.preferredVersion.split(".")[0], 10) || 0;
|
|
6164
|
+
const majorB = parseInt(b.preferredVersion.split(".")[0], 10) || 0;
|
|
6165
|
+
return majorB - majorA;
|
|
6166
|
+
});
|
|
6167
|
+
result.push(group[0]);
|
|
6168
|
+
}
|
|
6169
|
+
return result;
|
|
6170
|
+
}
|
|
6171
|
+
function filterAutoPatterns(patterns, mappings, detectedKeys, repoLanguages, filters) {
|
|
6172
|
+
const allMappedPrefixes = [];
|
|
6173
|
+
const prefixToKeys = /* @__PURE__ */ new Map();
|
|
6174
|
+
const allMappedTags = [];
|
|
6175
|
+
const tagToKeys = /* @__PURE__ */ new Map();
|
|
6176
|
+
if (mappings) {
|
|
6177
|
+
for (const [key, entry] of Object.entries(mappings)) {
|
|
6178
|
+
if (entry.prefixes) {
|
|
6179
|
+
for (const prefix of entry.prefixes) {
|
|
6180
|
+
allMappedPrefixes.push(prefix);
|
|
6181
|
+
const existing = prefixToKeys.get(prefix) ?? [];
|
|
6182
|
+
existing.push(key);
|
|
6183
|
+
prefixToKeys.set(prefix, existing);
|
|
6184
|
+
}
|
|
6185
|
+
}
|
|
6186
|
+
if (entry.tags) {
|
|
6187
|
+
for (const tag of entry.tags) {
|
|
6188
|
+
if (!allMappedTags.includes(tag)) allMappedTags.push(tag);
|
|
6189
|
+
const existing = tagToKeys.get(tag) ?? [];
|
|
6190
|
+
existing.push(key);
|
|
6191
|
+
tagToKeys.set(tag, existing);
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
}
|
|
6195
|
+
}
|
|
6196
|
+
const severityFilter = filters?.severities.length ? new Map(filters.severities.map((s) => [s.level, s.all])) : void 0;
|
|
6197
|
+
const categoryFilter = filters?.categories.length ? new Map(filters.categories.map((c) => [c.category, c.all])) : void 0;
|
|
6198
|
+
const result = [];
|
|
6199
|
+
for (const pattern of patterns) {
|
|
6200
|
+
const matchedKeys = findMappedKeys(
|
|
6201
|
+
pattern.id,
|
|
6202
|
+
pattern.tags,
|
|
6203
|
+
allMappedPrefixes,
|
|
6204
|
+
prefixToKeys,
|
|
6205
|
+
allMappedTags,
|
|
6206
|
+
tagToKeys
|
|
6207
|
+
);
|
|
6208
|
+
if (matchedKeys.length > 0) {
|
|
6209
|
+
if (!matchedKeys.some((k) => detectedKeys.has(k))) continue;
|
|
6210
|
+
} else {
|
|
6211
|
+
if (!pattern.enabled) {
|
|
6212
|
+
if (!isOverriddenByAllPrefix(pattern, severityFilter, categoryFilter)) {
|
|
6213
|
+
continue;
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
6216
|
+
}
|
|
6217
|
+
if (pattern.languages.length > 0 && repoLanguages.size > 0) {
|
|
6218
|
+
if (!pattern.languages.some((lang) => repoLanguages.has(lang))) continue;
|
|
6219
|
+
}
|
|
6220
|
+
if (severityFilter && !severityFilter.has(pattern.severityLevel)) continue;
|
|
6221
|
+
if (categoryFilter && !categoryFilter.has(pattern.category)) continue;
|
|
6222
|
+
result.push(pattern);
|
|
6223
|
+
}
|
|
6224
|
+
return result;
|
|
6225
|
+
}
|
|
6226
|
+
function findMappedKeys(patternId, patternTags, allPrefixes, prefixToKeys, allTags, tagToKeys) {
|
|
6227
|
+
const matched = /* @__PURE__ */ new Set();
|
|
6228
|
+
let longestPrefix = "";
|
|
6229
|
+
for (const prefix of allPrefixes) {
|
|
6230
|
+
if (patternId.startsWith(prefix) && prefix.length > longestPrefix.length) {
|
|
6231
|
+
longestPrefix = prefix;
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
if (longestPrefix) {
|
|
6235
|
+
const keys = prefixToKeys.get(longestPrefix);
|
|
6236
|
+
if (keys) for (const k of keys) matched.add(k);
|
|
6237
|
+
}
|
|
6238
|
+
if (patternTags && patternTags.length > 0 && allTags.length > 0) {
|
|
6239
|
+
for (const tag of patternTags) {
|
|
6240
|
+
const keys = tagToKeys.get(tag);
|
|
6241
|
+
if (keys) for (const k of keys) matched.add(k);
|
|
6242
|
+
}
|
|
6243
|
+
}
|
|
6244
|
+
return Array.from(matched);
|
|
6245
|
+
}
|
|
6246
|
+
function isOverriddenByAllPrefix(pattern, severityFilter, categoryFilter) {
|
|
6247
|
+
if (severityFilter) {
|
|
6248
|
+
const allFlag = severityFilter.get(pattern.severityLevel);
|
|
6249
|
+
if (allFlag === true) return true;
|
|
6250
|
+
}
|
|
6251
|
+
if (categoryFilter) {
|
|
6252
|
+
const allFlag = categoryFilter.get(pattern.category);
|
|
6253
|
+
if (allFlag === true) return true;
|
|
6254
|
+
}
|
|
6255
|
+
return false;
|
|
6256
|
+
}
|
|
6257
|
+
|
|
6258
|
+
// src/auto-filters.ts
|
|
6259
|
+
var SEVERITY_ALIASES = {
|
|
6260
|
+
info: "Info",
|
|
6261
|
+
minor: "Info",
|
|
6262
|
+
warning: "Warning",
|
|
6263
|
+
medium: "Warning",
|
|
6264
|
+
high: "High",
|
|
6265
|
+
error: "Error",
|
|
6266
|
+
critical: "Error"
|
|
6267
|
+
};
|
|
6268
|
+
var CATEGORY_NAMES = {
|
|
6269
|
+
security: "Security",
|
|
6270
|
+
errorprone: "ErrorProne",
|
|
6271
|
+
codestyle: "CodeStyle",
|
|
6272
|
+
compatibility: "Compatibility",
|
|
6273
|
+
performance: "Performance",
|
|
6274
|
+
unusedcode: "UnusedCode",
|
|
6275
|
+
complexity: "Complexity",
|
|
6276
|
+
comprehensibility: "Comprehensibility",
|
|
6277
|
+
bestpractice: "BestPractice",
|
|
6278
|
+
documentation: "Documentation"
|
|
6279
|
+
};
|
|
6280
|
+
function parseAutoFilters(raw) {
|
|
6281
|
+
const severities = [];
|
|
6282
|
+
const categories = [];
|
|
6283
|
+
const unknown = [];
|
|
6284
|
+
const tokens = raw.split(",").map((t) => t.trim()).filter(Boolean);
|
|
6285
|
+
for (const token of tokens) {
|
|
6286
|
+
let name = token;
|
|
6287
|
+
let all = false;
|
|
6288
|
+
if (name.toLowerCase().startsWith("all")) {
|
|
6289
|
+
all = true;
|
|
6290
|
+
name = name.slice(3);
|
|
6291
|
+
}
|
|
6292
|
+
const severityMatch = SEVERITY_ALIASES[name.toLowerCase()];
|
|
6293
|
+
if (severityMatch) {
|
|
6294
|
+
if (!severities.some((s) => s.level === severityMatch)) {
|
|
6295
|
+
severities.push({ level: severityMatch, all });
|
|
6296
|
+
} else {
|
|
6297
|
+
const existing = severities.find((s) => s.level === severityMatch);
|
|
6298
|
+
if (all) existing.all = true;
|
|
6299
|
+
}
|
|
6300
|
+
continue;
|
|
6301
|
+
}
|
|
6302
|
+
const categoryMatch = CATEGORY_NAMES[name.toLowerCase()];
|
|
6303
|
+
if (categoryMatch) {
|
|
6304
|
+
if (!categories.some((c) => c.category === categoryMatch)) {
|
|
6305
|
+
categories.push({ category: categoryMatch, all });
|
|
6306
|
+
} else {
|
|
6307
|
+
const existing = categories.find((c) => c.category === categoryMatch);
|
|
6308
|
+
if (all) existing.all = true;
|
|
6309
|
+
}
|
|
6310
|
+
continue;
|
|
6311
|
+
}
|
|
6312
|
+
unknown.push(token);
|
|
6313
|
+
}
|
|
6314
|
+
return { filters: { severities, categories }, unknown };
|
|
6315
|
+
}
|
|
5153
6316
|
|
|
5154
6317
|
// src/logger.ts
|
|
5155
6318
|
var import_fs = __toESM(require("fs"));
|
|
5156
|
-
var
|
|
6319
|
+
var import_path8 = __toESM(require("path"));
|
|
5157
6320
|
var import_os2 = __toESM(require("os"));
|
|
5158
6321
|
var LEVEL_ORDER = {
|
|
5159
6322
|
debug: 0,
|
|
@@ -5173,7 +6336,7 @@ function rotateLogFiles(logsDir, maxFiles) {
|
|
|
5173
6336
|
const toRemove = entries2.slice(0, entries2.length - maxFiles);
|
|
5174
6337
|
for (const f of toRemove) {
|
|
5175
6338
|
try {
|
|
5176
|
-
import_fs.default.unlinkSync(
|
|
6339
|
+
import_fs.default.unlinkSync(import_path8.default.join(logsDir, f));
|
|
5177
6340
|
} catch {
|
|
5178
6341
|
}
|
|
5179
6342
|
}
|
|
@@ -5208,7 +6371,7 @@ function enrichMessage(message, fields) {
|
|
|
5208
6371
|
function createLogger(options = {}) {
|
|
5209
6372
|
const minLevel = LEVEL_ORDER[options.level ?? "info"];
|
|
5210
6373
|
const fileEnabled = options.fileEnabled ?? true;
|
|
5211
|
-
const logsDir = options.logsDir ??
|
|
6374
|
+
const logsDir = options.logsDir ?? import_path8.default.join(import_os2.default.homedir(), ".codacy", "logs");
|
|
5212
6375
|
const maxFileSize = options.maxFileSize ?? 10 * 1024 * 1024;
|
|
5213
6376
|
const maxFiles = options.maxFiles ?? 5;
|
|
5214
6377
|
const onStderrMessage = options.onStderrMessage;
|
|
@@ -5217,7 +6380,7 @@ function createLogger(options = {}) {
|
|
|
5217
6380
|
if (fileEnabled) {
|
|
5218
6381
|
import_fs.default.mkdirSync(logsDir, { recursive: true });
|
|
5219
6382
|
rotateLogFiles(logsDir, maxFiles);
|
|
5220
|
-
const logFilePath =
|
|
6383
|
+
const logFilePath = import_path8.default.join(logsDir, `analysis-${fileTimestamp()}.log`);
|
|
5221
6384
|
logFd = import_fs.default.openSync(logFilePath, "a");
|
|
5222
6385
|
}
|
|
5223
6386
|
function log(level, message, fields) {
|
|
@@ -5236,7 +6399,7 @@ function createLogger(options = {}) {
|
|
|
5236
6399
|
if (bytesWritten >= maxFileSize) {
|
|
5237
6400
|
import_fs.default.closeSync(logFd);
|
|
5238
6401
|
rotateLogFiles(logsDir, maxFiles);
|
|
5239
|
-
const newPath =
|
|
6402
|
+
const newPath = import_path8.default.join(logsDir, `analysis-${fileTimestamp()}.log`);
|
|
5240
6403
|
logFd = import_fs.default.openSync(newPath, "a");
|
|
5241
6404
|
bytesWritten = 0;
|
|
5242
6405
|
}
|
|
@@ -5262,15 +6425,18 @@ function createLogger(options = {}) {
|
|
|
5262
6425
|
applyCodacyYamlExcludes,
|
|
5263
6426
|
buildToolConfig,
|
|
5264
6427
|
clearAdapters,
|
|
6428
|
+
computePatternSummary,
|
|
5265
6429
|
configureApiToken,
|
|
5266
6430
|
createCodacyConfig,
|
|
5267
6431
|
createLogger,
|
|
5268
6432
|
detectLanguages,
|
|
6433
|
+
discover,
|
|
5269
6434
|
formatOutput,
|
|
5270
6435
|
formatTextSummary,
|
|
5271
6436
|
getAdapter,
|
|
5272
6437
|
getRegisteredAdapters,
|
|
5273
6438
|
getRegisteredDescriptors,
|
|
6439
|
+
initAutoConfig,
|
|
5274
6440
|
initContainerConfig,
|
|
5275
6441
|
initDefaultConfig,
|
|
5276
6442
|
initLocalConfig,
|
|
@@ -5279,6 +6445,7 @@ function createLogger(options = {}) {
|
|
|
5279
6445
|
listIgnoredFiles,
|
|
5280
6446
|
listPrFiles,
|
|
5281
6447
|
listStagedFiles,
|
|
6448
|
+
parseAutoFilters,
|
|
5282
6449
|
readCodacyConfig,
|
|
5283
6450
|
readCodacyYaml,
|
|
5284
6451
|
registerAdapter,
|