@code-pushup/cli 0.8.24 → 0.8.25

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.
Files changed (2) hide show
  1. package/index.js +107 -136
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -573,15 +573,15 @@ function slugify(text) {
573
573
  return text.trim().toLowerCase().replace(/\s+|\//g, "-").replace(/[^a-z\d-]/g, "");
574
574
  }
575
575
  function formatBytes(bytes, decimals = 2) {
576
- bytes = Math.max(bytes, 0);
577
- if (!bytes) {
576
+ const positiveBytes = Math.max(bytes, 0);
577
+ if (positiveBytes === 0) {
578
578
  return "0 B";
579
579
  }
580
580
  const k = 1024;
581
581
  const dm = decimals < 0 ? 0 : decimals;
582
582
  const sizes = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
583
- const i = Math.floor(Math.log(bytes) / Math.log(k));
584
- return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
583
+ const i = Math.floor(Math.log(positiveBytes) / Math.log(k));
584
+ return `${Number.parseFloat((positiveBytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
585
585
  }
586
586
  function formatDuration(duration) {
587
587
  if (duration < 1e3) {
@@ -766,8 +766,7 @@ function getSeverityIcon(severity) {
766
766
  return "\u2139\uFE0F";
767
767
  }
768
768
  function calcDuration(start, stop) {
769
- stop ??= performance.now();
770
- return Math.floor(stop - start);
769
+ return Math.floor((stop ?? performance.now()) - start);
771
770
  }
772
771
  function countCategoryAudits(refs, plugins) {
773
772
  const groupLookup = plugins.reduce(
@@ -793,15 +792,15 @@ function countCategoryAudits(refs, plugins) {
793
792
  }, 0);
794
793
  }
795
794
  function getAuditByRef({ slug, weight, plugin }, plugins) {
796
- const auditPlugin = plugins.find(({ slug: slug2 }) => slug2 === plugin);
795
+ const auditPlugin = plugins.find((p) => p.slug === plugin);
797
796
  if (!auditPlugin) {
798
797
  throwIsNotPresentError(`Plugin ${plugin}`, "report");
799
798
  }
800
- const audit = auditPlugin?.audits.find(
799
+ const audit = auditPlugin.audits.find(
801
800
  ({ slug: auditSlug }) => auditSlug === slug
802
801
  );
803
802
  if (!audit) {
804
- throwIsNotPresentError(`Audit ${slug}`, auditPlugin?.slug);
803
+ throwIsNotPresentError(`Audit ${slug}`, auditPlugin.slug);
805
804
  }
806
805
  return {
807
806
  ...audit,
@@ -814,24 +813,21 @@ function getGroupWithAudits(refSlug, refPlugin, plugins) {
814
813
  if (!plugin) {
815
814
  throwIsNotPresentError(`Plugin ${refPlugin}`, "report");
816
815
  }
817
- const groupWithAudits = plugin?.groups?.find(({ slug }) => slug === refSlug);
816
+ const groupWithAudits = plugin.groups?.find(({ slug }) => slug === refSlug);
818
817
  if (!groupWithAudits) {
819
- throwIsNotPresentError(`Group ${refSlug}`, plugin?.slug);
818
+ throwIsNotPresentError(`Group ${refSlug}`, plugin.slug);
820
819
  }
821
820
  const groupAudits = groupWithAudits.refs.reduce(
822
821
  (acc, ref) => {
823
822
  const audit = getAuditByRef(
824
- { ...ref, plugin: refPlugin },
823
+ { ...ref, plugin: refPlugin, type: "audit" },
825
824
  plugins
826
825
  );
827
- if (audit) {
828
- return [...acc, audit];
829
- }
830
- return [...acc];
826
+ return [...acc, audit];
831
827
  },
832
828
  []
833
829
  );
834
- const audits = groupAudits.sort(compareCategoryAudits);
830
+ const audits = [...groupAudits].sort(compareCategoryAudits);
835
831
  return {
836
832
  ...groupWithAudits,
837
833
  audits
@@ -874,7 +870,8 @@ async function loadReport(options2) {
874
870
  const content = await readJsonFile(filePath);
875
871
  return reportSchema.parse(content);
876
872
  }
877
- return readTextFile(filePath);
873
+ const text = await readTextFile(filePath);
874
+ return text;
878
875
  }
879
876
  function throwIsNotPresentError(itemName, presentPlace) {
880
877
  throw new Error(`${itemName} is not present in ${presentPlace}`);
@@ -929,11 +926,11 @@ function executeProcess(cfg) {
929
926
  let stdout = "";
930
927
  let stderr = "";
931
928
  process2.stdout.on("data", (data) => {
932
- stdout += data.toString();
933
- onStdout?.(data);
929
+ stdout += String(data);
930
+ onStdout?.(String(data));
934
931
  });
935
932
  process2.stderr.on("data", (data) => {
936
- stderr += data.toString();
933
+ stderr += String(data);
937
934
  });
938
935
  process2.on("error", (err) => {
939
936
  stderr += err.toString();
@@ -953,28 +950,20 @@ function executeProcess(cfg) {
953
950
  }
954
951
 
955
952
  // packages/utils/src/lib/git.ts
956
- import simpleGit from "simple-git";
953
+ import { simpleGit } from "simple-git";
957
954
  var git = simpleGit();
958
955
  async function getLatestCommit() {
959
956
  const log = await git.log({
960
957
  maxCount: 1,
961
958
  format: { hash: "%H", message: "%s", author: "%an", date: "%ad" }
962
959
  });
963
- return log?.latest;
960
+ return log.latest;
964
961
  }
965
962
 
966
963
  // packages/utils/src/lib/group-by-status.ts
967
964
  function groupByStatus(results) {
968
965
  return results.reduce(
969
- (acc, result) => {
970
- if (result.status === "fulfilled") {
971
- return { ...acc, fulfilled: [...acc.fulfilled, result] };
972
- }
973
- if (result.status === "rejected") {
974
- return { ...acc, rejected: [...acc.rejected, result] };
975
- }
976
- return acc;
977
- },
966
+ (acc, result) => result.status === "fulfilled" ? { ...acc, fulfilled: [...acc.fulfilled, result] } : { ...acc, rejected: [...acc.rejected, result] },
978
967
  { fulfilled: [], rejected: [] }
979
968
  );
980
969
  }
@@ -1089,10 +1078,10 @@ function tableMd(data, align) {
1089
1078
  if (data.length === 0) {
1090
1079
  throw new Error("Data can't be empty");
1091
1080
  }
1092
- align ??= data[0]?.map(() => "c");
1081
+ const alignmentSetting = align ?? data[0]?.map(() => "c");
1093
1082
  const tableContent = data.map((arr) => `|${arr.join("|")}|`);
1094
- const secondRow = `|${align?.map((s) => alignString.get(s)).join("|")}|`;
1095
- return tableContent.shift() + NEW_LINE + secondRow + NEW_LINE + tableContent.join(NEW_LINE);
1083
+ const alignmentRow = `|${alignmentSetting?.map((s) => alignString.get(s)).join("|")}|`;
1084
+ return tableContent[0] + NEW_LINE + alignmentRow + NEW_LINE + tableContent.slice(1).join(NEW_LINE);
1096
1085
  }
1097
1086
  function tableHtml(data) {
1098
1087
  if (data.length === 0) {
@@ -1145,15 +1134,15 @@ function reportToCategoriesSection(report) {
1145
1134
  category.score
1146
1135
  )} Score: ${style(formatReportScore(category.score))}`;
1147
1136
  const categoryDocs = getDocsAndDescription(category);
1148
- const categoryMDItems = category.refs.reduce((acc2, ref) => {
1137
+ const categoryMDItems = category.refs.reduce((refAcc, ref) => {
1149
1138
  if (ref.type === "group") {
1150
1139
  const group = getGroupWithAudits(ref.slug, ref.plugin, plugins);
1151
1140
  const mdGroupItem = groupItemToCategorySection(group, plugins);
1152
- return acc2 + mdGroupItem + NEW_LINE;
1141
+ return refAcc + mdGroupItem + NEW_LINE;
1153
1142
  } else {
1154
1143
  const audit = getAuditByRef(ref, plugins);
1155
1144
  const mdAuditItem = auditItemToCategorySection(audit, plugins);
1156
- return acc2 + mdAuditItem + NEW_LINE;
1145
+ return refAcc + mdAuditItem + NEW_LINE;
1157
1146
  }
1158
1147
  }, "");
1159
1148
  return acc + NEW_LINE + categoryTitle + NEW_LINE + NEW_LINE + categoryDocs + categoryScore + NEW_LINE + categoryMDItems;
@@ -1164,7 +1153,7 @@ function auditItemToCategorySection(audit, plugins) {
1164
1153
  const pluginTitle = getPluginNameFromSlug(audit.plugin, plugins);
1165
1154
  const auditTitle = link(
1166
1155
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1167
- audit?.title
1156
+ audit.title
1168
1157
  );
1169
1158
  return li(
1170
1159
  `${getSquaredScoreMarker(
@@ -1181,69 +1170,57 @@ function groupItemToCategorySection(group, plugins) {
1181
1170
  const groupAudits = group.audits.reduce((acc, audit) => {
1182
1171
  const auditTitle = link(
1183
1172
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1184
- audit?.title
1173
+ audit.title
1185
1174
  );
1186
- acc += ` ${li(
1175
+ return `${acc} ${li(
1187
1176
  `${getSquaredScoreMarker(audit.score)} ${auditTitle} - ${getAuditResult(
1188
1177
  audit
1189
1178
  )}`
1190
- )}`;
1191
- acc += NEW_LINE;
1192
- return acc;
1179
+ )}${NEW_LINE}`;
1193
1180
  }, "");
1194
1181
  return groupTitle + NEW_LINE + groupAudits;
1195
1182
  }
1196
1183
  function reportToAuditsSection(report) {
1197
- const auditsSection = report.plugins.reduce((acc, plugin) => {
1198
- const auditsData = plugin.audits.reduce((acc2, audit) => {
1184
+ const auditsSection = report.plugins.reduce((pluginAcc, plugin) => {
1185
+ const auditsData = plugin.audits.reduce((auditAcc, audit) => {
1199
1186
  const auditTitle = `${audit.title} (${getPluginNameFromSlug(
1200
1187
  audit.plugin,
1201
1188
  report.plugins
1202
1189
  )})`;
1203
- const detailsTitle = `${getSquaredScoreMarker(
1204
- audit.score
1205
- )} ${getAuditResult(audit, true)} (score: ${formatReportScore(
1206
- audit.score
1207
- )})`;
1208
- const docsItem = getDocsAndDescription(audit);
1209
- acc2 += h3(auditTitle);
1210
- acc2 += NEW_LINE;
1211
- acc2 += NEW_LINE;
1212
- if (!audit.details?.issues?.length) {
1213
- acc2 += detailsTitle;
1214
- acc2 += NEW_LINE;
1215
- acc2 += NEW_LINE;
1216
- acc2 += docsItem;
1217
- return acc2;
1218
- }
1219
- const detailsTableData = [
1220
- detailsTableHeaders,
1221
- ...audit.details.issues.map((issue) => {
1222
- const severity = `${getSeverityIcon(issue.severity)} <i>${issue.severity}</i>`;
1223
- const message = issue.message;
1224
- if (!issue.source) {
1225
- return [severity, message, "", ""];
1226
- }
1227
- const file = `<code>${issue.source?.file}</code>`;
1228
- if (!issue.source.position) {
1229
- return [severity, message, file, ""];
1230
- }
1231
- const { startLine, endLine } = issue.source.position;
1232
- const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
1233
- return [severity, message, file, line];
1234
- })
1235
- ];
1236
- const detailsTable = `<h4>Issues</h4>${tableHtml(detailsTableData)}`;
1237
- acc2 += details(detailsTitle, detailsTable);
1238
- acc2 += NEW_LINE;
1239
- acc2 += NEW_LINE;
1240
- acc2 += docsItem;
1241
- return acc2;
1190
+ return auditAcc + h3(auditTitle) + NEW_LINE + NEW_LINE + reportToDetailsSection(audit) + NEW_LINE + NEW_LINE + getDocsAndDescription(audit);
1242
1191
  }, "");
1243
- return acc + auditsData;
1192
+ return pluginAcc + auditsData;
1244
1193
  }, "");
1245
1194
  return h2("\u{1F6E1}\uFE0F Audits") + NEW_LINE + NEW_LINE + auditsSection;
1246
1195
  }
1196
+ function reportToDetailsSection(audit) {
1197
+ const detailsTitle = `${getSquaredScoreMarker(audit.score)} ${getAuditResult(
1198
+ audit,
1199
+ true
1200
+ )} (score: ${formatReportScore(audit.score)})`;
1201
+ if (!audit.details?.issues.length) {
1202
+ return detailsTitle;
1203
+ }
1204
+ const detailsTableData = [
1205
+ detailsTableHeaders,
1206
+ ...audit.details.issues.map((issue) => {
1207
+ const severity = `${getSeverityIcon(issue.severity)} <i>${issue.severity}</i>`;
1208
+ const message = issue.message;
1209
+ if (!issue.source) {
1210
+ return [severity, message, "", ""];
1211
+ }
1212
+ const file = `<code>${issue.source.file}</code>`;
1213
+ if (!issue.source.position) {
1214
+ return [severity, message, file, ""];
1215
+ }
1216
+ const { startLine, endLine } = issue.source.position;
1217
+ const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
1218
+ return [severity, message, file, line];
1219
+ })
1220
+ ];
1221
+ const detailsTable = `<h4>Issues</h4>${tableHtml(detailsTableData)}`;
1222
+ return details(detailsTitle, detailsTable);
1223
+ }
1247
1224
  function reportToAboutSection(report, commitData) {
1248
1225
  const date = (/* @__PURE__ */ new Date()).toString();
1249
1226
  const { duration, version: version2, plugins, categories } = report;
@@ -1261,11 +1238,11 @@ function reportToAboutSection(report, commitData) {
1261
1238
  ];
1262
1239
  const pluginMetaTable = [
1263
1240
  pluginMetaTableHeaders,
1264
- ...plugins.map(({ title, version: version3, duration: duration2, audits }) => [
1265
- title,
1266
- audits.length.toString(),
1267
- style(version3 || "", ["c"]),
1268
- formatDuration(duration2)
1241
+ ...plugins.map((plugin) => [
1242
+ plugin.title,
1243
+ plugin.audits.length.toString(),
1244
+ style(plugin.version || "", ["c"]),
1245
+ formatDuration(plugin.duration)
1269
1246
  ])
1270
1247
  ];
1271
1248
  return (
@@ -1300,7 +1277,7 @@ function getAuditResult(audit, isHtml = false) {
1300
1277
  // packages/utils/src/lib/reports/generate-stdout-summary.ts
1301
1278
  import cliui from "@isaacs/cliui";
1302
1279
  import chalk3 from "chalk";
1303
- import Table from "cli-table3";
1280
+ import CliTable3 from "cli-table3";
1304
1281
  function addLine(line = "") {
1305
1282
  return line + NEW_LINE;
1306
1283
  }
@@ -1316,20 +1293,20 @@ function reportToDetailSection(report) {
1316
1293
  return plugins.reduce((acc, plugin) => {
1317
1294
  const { title, audits } = plugin;
1318
1295
  const ui = cliui({ width: TERMINAL_WIDTH });
1319
- audits.forEach(({ score, title: title2, displayValue, value }) => {
1296
+ audits.forEach((audit) => {
1320
1297
  ui.div(
1321
1298
  {
1322
- text: withColor({ score, text: "\u25CF" }),
1299
+ text: withColor({ score: audit.score, text: "\u25CF" }),
1323
1300
  width: 2,
1324
1301
  padding: [0, 1, 0, 0]
1325
1302
  },
1326
1303
  {
1327
- text: title2,
1304
+ text: audit.title,
1328
1305
  // eslint-disable-next-line no-magic-numbers
1329
1306
  padding: [0, 3, 0, 0]
1330
1307
  },
1331
1308
  {
1332
- text: chalk3.cyanBright(displayValue || `${value}`),
1309
+ text: chalk3.cyanBright(audit.displayValue || `${audit.value}`),
1333
1310
  width: 10,
1334
1311
  padding: [0, 0, 0, 0]
1335
1312
  }
@@ -1342,7 +1319,7 @@ function reportToOverviewSection2({
1342
1319
  categories,
1343
1320
  plugins
1344
1321
  }) {
1345
- const table = new Table({
1322
+ const table = new CliTable3({
1346
1323
  head: reportRawOverviewTableHeaders,
1347
1324
  colAligns: ["left", "right", "right"],
1348
1325
  style: {
@@ -1375,16 +1352,7 @@ function toArray(val) {
1375
1352
  return Array.isArray(val) ? val : [val];
1376
1353
  }
1377
1354
  function deepClone(obj) {
1378
- if (obj == null || typeof obj !== "object") {
1379
- return obj;
1380
- }
1381
- const cloned = Array.isArray(obj) ? [] : {};
1382
- for (const key in obj) {
1383
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
1384
- cloned[key] = deepClone(obj[key]);
1385
- }
1386
- }
1387
- return cloned;
1355
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1388
1356
  }
1389
1357
 
1390
1358
  // packages/utils/src/lib/reports/scoring.ts
@@ -1407,15 +1375,12 @@ function calculateScore(refs, scoreFn) {
1407
1375
  return numerator / denominator;
1408
1376
  }
1409
1377
  function scoreReport(report) {
1410
- const scoredReport = deepClone(report);
1411
1378
  const allScoredAuditsAndGroups = /* @__PURE__ */ new Map();
1412
- scoredReport.plugins?.forEach((plugin) => {
1413
- const { slug, audits } = plugin;
1414
- const groups = plugin.groups || [];
1415
- audits.forEach((audit) => {
1416
- const key = `${slug}-${audit.slug}-audit`;
1417
- audit.plugin = slug;
1418
- allScoredAuditsAndGroups.set(key, audit);
1379
+ const scoredPlugins = report.plugins.map((plugin) => {
1380
+ const { slug, audits, groups } = plugin;
1381
+ const updatedAudits = audits.map((audit) => ({ ...audit, plugin: slug }));
1382
+ updatedAudits.forEach((audit) => {
1383
+ allScoredAuditsAndGroups.set(`${slug}-${audit.slug}-audit`, audit);
1419
1384
  });
1420
1385
  function groupScoreFn(ref) {
1421
1386
  const score = allScoredAuditsAndGroups.get(
@@ -1428,13 +1393,15 @@ function scoreReport(report) {
1428
1393
  }
1429
1394
  return score;
1430
1395
  }
1431
- groups.forEach((group) => {
1432
- const key = `${slug}-${group.slug}-group`;
1433
- group.score = calculateScore(group.refs, groupScoreFn);
1434
- group.plugin = slug;
1435
- allScoredAuditsAndGroups.set(key, group);
1396
+ const scoredGroups = groups?.map((group) => ({
1397
+ ...group,
1398
+ score: calculateScore(group.refs, groupScoreFn),
1399
+ plugin: slug
1400
+ })) ?? [];
1401
+ scoredGroups.forEach((group) => {
1402
+ allScoredAuditsAndGroups.set(`${slug}-${group.slug}-group`, group);
1436
1403
  });
1437
- plugin.groups = groups;
1404
+ return { ...plugin, audits: updatedAudits, groups: scoredGroups };
1438
1405
  });
1439
1406
  function catScoreFn(ref) {
1440
1407
  const key = `${ref.plugin}-${ref.slug}-${ref.type}`;
@@ -1446,13 +1413,15 @@ function scoreReport(report) {
1446
1413
  }
1447
1414
  return item.score;
1448
1415
  }
1449
- const scoredCategoriesMap = /* @__PURE__ */ new Map();
1450
- for (const category of scoredReport.categories) {
1451
- category.score = calculateScore(category.refs, catScoreFn);
1452
- scoredCategoriesMap.set(category.slug, category);
1453
- }
1454
- scoredReport.categories = [...scoredCategoriesMap.values()];
1455
- return scoredReport;
1416
+ const scoredCategories = report.categories.map((category) => ({
1417
+ ...category,
1418
+ score: calculateScore(category.refs, catScoreFn)
1419
+ }));
1420
+ return {
1421
+ ...deepClone(report),
1422
+ plugins: scoredPlugins,
1423
+ categories: scoredCategories
1424
+ };
1456
1425
  }
1457
1426
 
1458
1427
  // packages/utils/src/lib/reports/sorting.ts
@@ -1475,7 +1444,7 @@ function sortReport(report) {
1475
1444
  );
1476
1445
  const sortedAuditsAndGroups = [
1477
1446
  ...groups,
1478
- ...audits.sort(compareCategoryAudits)
1447
+ ...[...audits].sort(compareCategoryAudits)
1479
1448
  ];
1480
1449
  const sortedRefs = [...category.refs].sort((a, b) => {
1481
1450
  const aIndex = sortedAuditsAndGroups.findIndex(
@@ -1488,7 +1457,14 @@ function sortReport(report) {
1488
1457
  });
1489
1458
  return { ...category, refs: sortedRefs };
1490
1459
  });
1491
- const sortedPlugins = plugins.map((plugin) => ({
1460
+ return {
1461
+ ...report,
1462
+ categories: sortedCategories,
1463
+ plugins: sortPlugins(plugins)
1464
+ };
1465
+ }
1466
+ function sortPlugins(plugins) {
1467
+ return plugins.map((plugin) => ({
1492
1468
  ...plugin,
1493
1469
  audits: [...plugin.audits].sort(compareAudits).map(
1494
1470
  (audit) => audit.details?.issues ? {
@@ -1500,11 +1476,6 @@ function sortReport(report) {
1500
1476
  } : audit
1501
1477
  )
1502
1478
  }));
1503
- return {
1504
- ...report,
1505
- categories: sortedCategories,
1506
- plugins: sortedPlugins
1507
- };
1508
1479
  }
1509
1480
 
1510
1481
  // packages/utils/src/lib/verbose-utils.ts
@@ -1704,7 +1675,7 @@ function auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits)
1704
1675
 
1705
1676
  // packages/core/package.json
1706
1677
  var name = "@code-pushup/core";
1707
- var version = "0.8.24";
1678
+ var version = "0.8.25";
1708
1679
 
1709
1680
  // packages/core/src/lib/implementation/collect.ts
1710
1681
  async function collect(options2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/cli",
3
- "version": "0.8.24",
3
+ "version": "0.8.25",
4
4
  "bin": {
5
5
  "code-pushup": "index.js"
6
6
  },