@code-pushup/core 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
@@ -565,15 +565,15 @@ function slugify(text) {
565
565
  return text.trim().toLowerCase().replace(/\s+|\//g, "-").replace(/[^a-z\d-]/g, "");
566
566
  }
567
567
  function formatBytes(bytes, decimals = 2) {
568
- bytes = Math.max(bytes, 0);
569
- if (!bytes) {
568
+ const positiveBytes = Math.max(bytes, 0);
569
+ if (positiveBytes === 0) {
570
570
  return "0 B";
571
571
  }
572
572
  const k = 1024;
573
573
  const dm = decimals < 0 ? 0 : decimals;
574
574
  const sizes = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
575
- const i = Math.floor(Math.log(bytes) / Math.log(k));
576
- return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
575
+ const i = Math.floor(Math.log(positiveBytes) / Math.log(k));
576
+ return `${Number.parseFloat((positiveBytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
577
577
  }
578
578
  function formatDuration(duration) {
579
579
  if (duration < 1e3) {
@@ -758,8 +758,7 @@ function getSeverityIcon(severity) {
758
758
  return "\u2139\uFE0F";
759
759
  }
760
760
  function calcDuration(start, stop) {
761
- stop ??= performance.now();
762
- return Math.floor(stop - start);
761
+ return Math.floor((stop ?? performance.now()) - start);
763
762
  }
764
763
  function countCategoryAudits(refs, plugins) {
765
764
  const groupLookup = plugins.reduce(
@@ -785,15 +784,15 @@ function countCategoryAudits(refs, plugins) {
785
784
  }, 0);
786
785
  }
787
786
  function getAuditByRef({ slug, weight, plugin }, plugins) {
788
- const auditPlugin = plugins.find(({ slug: slug2 }) => slug2 === plugin);
787
+ const auditPlugin = plugins.find((p) => p.slug === plugin);
789
788
  if (!auditPlugin) {
790
789
  throwIsNotPresentError(`Plugin ${plugin}`, "report");
791
790
  }
792
- const audit = auditPlugin?.audits.find(
791
+ const audit = auditPlugin.audits.find(
793
792
  ({ slug: auditSlug }) => auditSlug === slug
794
793
  );
795
794
  if (!audit) {
796
- throwIsNotPresentError(`Audit ${slug}`, auditPlugin?.slug);
795
+ throwIsNotPresentError(`Audit ${slug}`, auditPlugin.slug);
797
796
  }
798
797
  return {
799
798
  ...audit,
@@ -806,24 +805,21 @@ function getGroupWithAudits(refSlug, refPlugin, plugins) {
806
805
  if (!plugin) {
807
806
  throwIsNotPresentError(`Plugin ${refPlugin}`, "report");
808
807
  }
809
- const groupWithAudits = plugin?.groups?.find(({ slug }) => slug === refSlug);
808
+ const groupWithAudits = plugin.groups?.find(({ slug }) => slug === refSlug);
810
809
  if (!groupWithAudits) {
811
- throwIsNotPresentError(`Group ${refSlug}`, plugin?.slug);
810
+ throwIsNotPresentError(`Group ${refSlug}`, plugin.slug);
812
811
  }
813
812
  const groupAudits = groupWithAudits.refs.reduce(
814
813
  (acc, ref) => {
815
814
  const audit = getAuditByRef(
816
- { ...ref, plugin: refPlugin },
815
+ { ...ref, plugin: refPlugin, type: "audit" },
817
816
  plugins
818
817
  );
819
- if (audit) {
820
- return [...acc, audit];
821
- }
822
- return [...acc];
818
+ return [...acc, audit];
823
819
  },
824
820
  []
825
821
  );
826
- const audits = groupAudits.sort(compareCategoryAudits);
822
+ const audits = [...groupAudits].sort(compareCategoryAudits);
827
823
  return {
828
824
  ...groupWithAudits,
829
825
  audits
@@ -866,7 +862,8 @@ async function loadReport(options) {
866
862
  const content = await readJsonFile(filePath);
867
863
  return reportSchema.parse(content);
868
864
  }
869
- return readTextFile(filePath);
865
+ const text = await readTextFile(filePath);
866
+ return text;
870
867
  }
871
868
  function throwIsNotPresentError(itemName, presentPlace) {
872
869
  throw new Error(`${itemName} is not present in ${presentPlace}`);
@@ -921,11 +918,11 @@ function executeProcess(cfg) {
921
918
  let stdout = "";
922
919
  let stderr = "";
923
920
  process2.stdout.on("data", (data) => {
924
- stdout += data.toString();
925
- onStdout?.(data);
921
+ stdout += String(data);
922
+ onStdout?.(String(data));
926
923
  });
927
924
  process2.stderr.on("data", (data) => {
928
- stderr += data.toString();
925
+ stderr += String(data);
929
926
  });
930
927
  process2.on("error", (err) => {
931
928
  stderr += err.toString();
@@ -945,28 +942,20 @@ function executeProcess(cfg) {
945
942
  }
946
943
 
947
944
  // packages/utils/src/lib/git.ts
948
- import simpleGit from "simple-git";
945
+ import { simpleGit } from "simple-git";
949
946
  var git = simpleGit();
950
947
  async function getLatestCommit() {
951
948
  const log = await git.log({
952
949
  maxCount: 1,
953
950
  format: { hash: "%H", message: "%s", author: "%an", date: "%ad" }
954
951
  });
955
- return log?.latest;
952
+ return log.latest;
956
953
  }
957
954
 
958
955
  // packages/utils/src/lib/group-by-status.ts
959
956
  function groupByStatus(results) {
960
957
  return results.reduce(
961
- (acc, result) => {
962
- if (result.status === "fulfilled") {
963
- return { ...acc, fulfilled: [...acc.fulfilled, result] };
964
- }
965
- if (result.status === "rejected") {
966
- return { ...acc, rejected: [...acc.rejected, result] };
967
- }
968
- return acc;
969
- },
958
+ (acc, result) => result.status === "fulfilled" ? { ...acc, fulfilled: [...acc.fulfilled, result] } : { ...acc, rejected: [...acc.rejected, result] },
970
959
  { fulfilled: [], rejected: [] }
971
960
  );
972
961
  }
@@ -1081,10 +1070,10 @@ function tableMd(data, align) {
1081
1070
  if (data.length === 0) {
1082
1071
  throw new Error("Data can't be empty");
1083
1072
  }
1084
- align ??= data[0]?.map(() => "c");
1073
+ const alignmentSetting = align ?? data[0]?.map(() => "c");
1085
1074
  const tableContent = data.map((arr) => `|${arr.join("|")}|`);
1086
- const secondRow = `|${align?.map((s) => alignString.get(s)).join("|")}|`;
1087
- return tableContent.shift() + NEW_LINE + secondRow + NEW_LINE + tableContent.join(NEW_LINE);
1075
+ const alignmentRow = `|${alignmentSetting?.map((s) => alignString.get(s)).join("|")}|`;
1076
+ return tableContent[0] + NEW_LINE + alignmentRow + NEW_LINE + tableContent.slice(1).join(NEW_LINE);
1088
1077
  }
1089
1078
  function tableHtml(data) {
1090
1079
  if (data.length === 0) {
@@ -1137,15 +1126,15 @@ function reportToCategoriesSection(report) {
1137
1126
  category.score
1138
1127
  )} Score: ${style(formatReportScore(category.score))}`;
1139
1128
  const categoryDocs = getDocsAndDescription(category);
1140
- const categoryMDItems = category.refs.reduce((acc2, ref) => {
1129
+ const categoryMDItems = category.refs.reduce((refAcc, ref) => {
1141
1130
  if (ref.type === "group") {
1142
1131
  const group = getGroupWithAudits(ref.slug, ref.plugin, plugins);
1143
1132
  const mdGroupItem = groupItemToCategorySection(group, plugins);
1144
- return acc2 + mdGroupItem + NEW_LINE;
1133
+ return refAcc + mdGroupItem + NEW_LINE;
1145
1134
  } else {
1146
1135
  const audit = getAuditByRef(ref, plugins);
1147
1136
  const mdAuditItem = auditItemToCategorySection(audit, plugins);
1148
- return acc2 + mdAuditItem + NEW_LINE;
1137
+ return refAcc + mdAuditItem + NEW_LINE;
1149
1138
  }
1150
1139
  }, "");
1151
1140
  return acc + NEW_LINE + categoryTitle + NEW_LINE + NEW_LINE + categoryDocs + categoryScore + NEW_LINE + categoryMDItems;
@@ -1156,7 +1145,7 @@ function auditItemToCategorySection(audit, plugins) {
1156
1145
  const pluginTitle = getPluginNameFromSlug(audit.plugin, plugins);
1157
1146
  const auditTitle = link(
1158
1147
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1159
- audit?.title
1148
+ audit.title
1160
1149
  );
1161
1150
  return li(
1162
1151
  `${getSquaredScoreMarker(
@@ -1173,69 +1162,57 @@ function groupItemToCategorySection(group, plugins) {
1173
1162
  const groupAudits = group.audits.reduce((acc, audit) => {
1174
1163
  const auditTitle = link(
1175
1164
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1176
- audit?.title
1165
+ audit.title
1177
1166
  );
1178
- acc += ` ${li(
1167
+ return `${acc} ${li(
1179
1168
  `${getSquaredScoreMarker(audit.score)} ${auditTitle} - ${getAuditResult(
1180
1169
  audit
1181
1170
  )}`
1182
- )}`;
1183
- acc += NEW_LINE;
1184
- return acc;
1171
+ )}${NEW_LINE}`;
1185
1172
  }, "");
1186
1173
  return groupTitle + NEW_LINE + groupAudits;
1187
1174
  }
1188
1175
  function reportToAuditsSection(report) {
1189
- const auditsSection = report.plugins.reduce((acc, plugin) => {
1190
- const auditsData = plugin.audits.reduce((acc2, audit) => {
1176
+ const auditsSection = report.plugins.reduce((pluginAcc, plugin) => {
1177
+ const auditsData = plugin.audits.reduce((auditAcc, audit) => {
1191
1178
  const auditTitle = `${audit.title} (${getPluginNameFromSlug(
1192
1179
  audit.plugin,
1193
1180
  report.plugins
1194
1181
  )})`;
1195
- const detailsTitle = `${getSquaredScoreMarker(
1196
- audit.score
1197
- )} ${getAuditResult(audit, true)} (score: ${formatReportScore(
1198
- audit.score
1199
- )})`;
1200
- const docsItem = getDocsAndDescription(audit);
1201
- acc2 += h3(auditTitle);
1202
- acc2 += NEW_LINE;
1203
- acc2 += NEW_LINE;
1204
- if (!audit.details?.issues?.length) {
1205
- acc2 += detailsTitle;
1206
- acc2 += NEW_LINE;
1207
- acc2 += NEW_LINE;
1208
- acc2 += docsItem;
1209
- return acc2;
1210
- }
1211
- const detailsTableData = [
1212
- detailsTableHeaders,
1213
- ...audit.details.issues.map((issue) => {
1214
- const severity = `${getSeverityIcon(issue.severity)} <i>${issue.severity}</i>`;
1215
- const message = issue.message;
1216
- if (!issue.source) {
1217
- return [severity, message, "", ""];
1218
- }
1219
- const file = `<code>${issue.source?.file}</code>`;
1220
- if (!issue.source.position) {
1221
- return [severity, message, file, ""];
1222
- }
1223
- const { startLine, endLine } = issue.source.position;
1224
- const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
1225
- return [severity, message, file, line];
1226
- })
1227
- ];
1228
- const detailsTable = `<h4>Issues</h4>${tableHtml(detailsTableData)}`;
1229
- acc2 += details(detailsTitle, detailsTable);
1230
- acc2 += NEW_LINE;
1231
- acc2 += NEW_LINE;
1232
- acc2 += docsItem;
1233
- return acc2;
1182
+ return auditAcc + h3(auditTitle) + NEW_LINE + NEW_LINE + reportToDetailsSection(audit) + NEW_LINE + NEW_LINE + getDocsAndDescription(audit);
1234
1183
  }, "");
1235
- return acc + auditsData;
1184
+ return pluginAcc + auditsData;
1236
1185
  }, "");
1237
1186
  return h2("\u{1F6E1}\uFE0F Audits") + NEW_LINE + NEW_LINE + auditsSection;
1238
1187
  }
1188
+ function reportToDetailsSection(audit) {
1189
+ const detailsTitle = `${getSquaredScoreMarker(audit.score)} ${getAuditResult(
1190
+ audit,
1191
+ true
1192
+ )} (score: ${formatReportScore(audit.score)})`;
1193
+ if (!audit.details?.issues.length) {
1194
+ return detailsTitle;
1195
+ }
1196
+ const detailsTableData = [
1197
+ detailsTableHeaders,
1198
+ ...audit.details.issues.map((issue) => {
1199
+ const severity = `${getSeverityIcon(issue.severity)} <i>${issue.severity}</i>`;
1200
+ const message = issue.message;
1201
+ if (!issue.source) {
1202
+ return [severity, message, "", ""];
1203
+ }
1204
+ const file = `<code>${issue.source.file}</code>`;
1205
+ if (!issue.source.position) {
1206
+ return [severity, message, file, ""];
1207
+ }
1208
+ const { startLine, endLine } = issue.source.position;
1209
+ const line = `${startLine || ""}${endLine && startLine !== endLine ? `-${endLine}` : ""}`;
1210
+ return [severity, message, file, line];
1211
+ })
1212
+ ];
1213
+ const detailsTable = `<h4>Issues</h4>${tableHtml(detailsTableData)}`;
1214
+ return details(detailsTitle, detailsTable);
1215
+ }
1239
1216
  function reportToAboutSection(report, commitData) {
1240
1217
  const date = (/* @__PURE__ */ new Date()).toString();
1241
1218
  const { duration, version: version2, plugins, categories } = report;
@@ -1253,11 +1230,11 @@ function reportToAboutSection(report, commitData) {
1253
1230
  ];
1254
1231
  const pluginMetaTable = [
1255
1232
  pluginMetaTableHeaders,
1256
- ...plugins.map(({ title, version: version3, duration: duration2, audits }) => [
1257
- title,
1258
- audits.length.toString(),
1259
- style(version3 || "", ["c"]),
1260
- formatDuration(duration2)
1233
+ ...plugins.map((plugin) => [
1234
+ plugin.title,
1235
+ plugin.audits.length.toString(),
1236
+ style(plugin.version || "", ["c"]),
1237
+ formatDuration(plugin.duration)
1261
1238
  ])
1262
1239
  ];
1263
1240
  return (
@@ -1292,7 +1269,7 @@ function getAuditResult(audit, isHtml = false) {
1292
1269
  // packages/utils/src/lib/reports/generate-stdout-summary.ts
1293
1270
  import cliui from "@isaacs/cliui";
1294
1271
  import chalk3 from "chalk";
1295
- import Table from "cli-table3";
1272
+ import CliTable3 from "cli-table3";
1296
1273
  function addLine(line = "") {
1297
1274
  return line + NEW_LINE;
1298
1275
  }
@@ -1308,20 +1285,20 @@ function reportToDetailSection(report) {
1308
1285
  return plugins.reduce((acc, plugin) => {
1309
1286
  const { title, audits } = plugin;
1310
1287
  const ui = cliui({ width: TERMINAL_WIDTH });
1311
- audits.forEach(({ score, title: title2, displayValue, value }) => {
1288
+ audits.forEach((audit) => {
1312
1289
  ui.div(
1313
1290
  {
1314
- text: withColor({ score, text: "\u25CF" }),
1291
+ text: withColor({ score: audit.score, text: "\u25CF" }),
1315
1292
  width: 2,
1316
1293
  padding: [0, 1, 0, 0]
1317
1294
  },
1318
1295
  {
1319
- text: title2,
1296
+ text: audit.title,
1320
1297
  // eslint-disable-next-line no-magic-numbers
1321
1298
  padding: [0, 3, 0, 0]
1322
1299
  },
1323
1300
  {
1324
- text: chalk3.cyanBright(displayValue || `${value}`),
1301
+ text: chalk3.cyanBright(audit.displayValue || `${audit.value}`),
1325
1302
  width: 10,
1326
1303
  padding: [0, 0, 0, 0]
1327
1304
  }
@@ -1334,7 +1311,7 @@ function reportToOverviewSection2({
1334
1311
  categories,
1335
1312
  plugins
1336
1313
  }) {
1337
- const table = new Table({
1314
+ const table = new CliTable3({
1338
1315
  head: reportRawOverviewTableHeaders,
1339
1316
  colAligns: ["left", "right", "right"],
1340
1317
  style: {
@@ -1367,16 +1344,7 @@ function toArray(val) {
1367
1344
  return Array.isArray(val) ? val : [val];
1368
1345
  }
1369
1346
  function deepClone(obj) {
1370
- if (obj == null || typeof obj !== "object") {
1371
- return obj;
1372
- }
1373
- const cloned = Array.isArray(obj) ? [] : {};
1374
- for (const key in obj) {
1375
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
1376
- cloned[key] = deepClone(obj[key]);
1377
- }
1378
- }
1379
- return cloned;
1347
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1380
1348
  }
1381
1349
 
1382
1350
  // packages/utils/src/lib/reports/scoring.ts
@@ -1399,15 +1367,12 @@ function calculateScore(refs, scoreFn) {
1399
1367
  return numerator / denominator;
1400
1368
  }
1401
1369
  function scoreReport(report) {
1402
- const scoredReport = deepClone(report);
1403
1370
  const allScoredAuditsAndGroups = /* @__PURE__ */ new Map();
1404
- scoredReport.plugins?.forEach((plugin) => {
1405
- const { slug, audits } = plugin;
1406
- const groups = plugin.groups || [];
1407
- audits.forEach((audit) => {
1408
- const key = `${slug}-${audit.slug}-audit`;
1409
- audit.plugin = slug;
1410
- allScoredAuditsAndGroups.set(key, audit);
1371
+ const scoredPlugins = report.plugins.map((plugin) => {
1372
+ const { slug, audits, groups } = plugin;
1373
+ const updatedAudits = audits.map((audit) => ({ ...audit, plugin: slug }));
1374
+ updatedAudits.forEach((audit) => {
1375
+ allScoredAuditsAndGroups.set(`${slug}-${audit.slug}-audit`, audit);
1411
1376
  });
1412
1377
  function groupScoreFn(ref) {
1413
1378
  const score = allScoredAuditsAndGroups.get(
@@ -1420,13 +1385,15 @@ function scoreReport(report) {
1420
1385
  }
1421
1386
  return score;
1422
1387
  }
1423
- groups.forEach((group) => {
1424
- const key = `${slug}-${group.slug}-group`;
1425
- group.score = calculateScore(group.refs, groupScoreFn);
1426
- group.plugin = slug;
1427
- allScoredAuditsAndGroups.set(key, group);
1388
+ const scoredGroups = groups?.map((group) => ({
1389
+ ...group,
1390
+ score: calculateScore(group.refs, groupScoreFn),
1391
+ plugin: slug
1392
+ })) ?? [];
1393
+ scoredGroups.forEach((group) => {
1394
+ allScoredAuditsAndGroups.set(`${slug}-${group.slug}-group`, group);
1428
1395
  });
1429
- plugin.groups = groups;
1396
+ return { ...plugin, audits: updatedAudits, groups: scoredGroups };
1430
1397
  });
1431
1398
  function catScoreFn(ref) {
1432
1399
  const key = `${ref.plugin}-${ref.slug}-${ref.type}`;
@@ -1438,13 +1405,15 @@ function scoreReport(report) {
1438
1405
  }
1439
1406
  return item.score;
1440
1407
  }
1441
- const scoredCategoriesMap = /* @__PURE__ */ new Map();
1442
- for (const category of scoredReport.categories) {
1443
- category.score = calculateScore(category.refs, catScoreFn);
1444
- scoredCategoriesMap.set(category.slug, category);
1445
- }
1446
- scoredReport.categories = [...scoredCategoriesMap.values()];
1447
- return scoredReport;
1408
+ const scoredCategories = report.categories.map((category) => ({
1409
+ ...category,
1410
+ score: calculateScore(category.refs, catScoreFn)
1411
+ }));
1412
+ return {
1413
+ ...deepClone(report),
1414
+ plugins: scoredPlugins,
1415
+ categories: scoredCategories
1416
+ };
1448
1417
  }
1449
1418
 
1450
1419
  // packages/utils/src/lib/reports/sorting.ts
@@ -1467,7 +1436,7 @@ function sortReport(report) {
1467
1436
  );
1468
1437
  const sortedAuditsAndGroups = [
1469
1438
  ...groups,
1470
- ...audits.sort(compareCategoryAudits)
1439
+ ...[...audits].sort(compareCategoryAudits)
1471
1440
  ];
1472
1441
  const sortedRefs = [...category.refs].sort((a, b) => {
1473
1442
  const aIndex = sortedAuditsAndGroups.findIndex(
@@ -1480,7 +1449,14 @@ function sortReport(report) {
1480
1449
  });
1481
1450
  return { ...category, refs: sortedRefs };
1482
1451
  });
1483
- const sortedPlugins = plugins.map((plugin) => ({
1452
+ return {
1453
+ ...report,
1454
+ categories: sortedCategories,
1455
+ plugins: sortPlugins(plugins)
1456
+ };
1457
+ }
1458
+ function sortPlugins(plugins) {
1459
+ return plugins.map((plugin) => ({
1484
1460
  ...plugin,
1485
1461
  audits: [...plugin.audits].sort(compareAudits).map(
1486
1462
  (audit) => audit.details?.issues ? {
@@ -1492,11 +1468,6 @@ function sortReport(report) {
1492
1468
  } : audit
1493
1469
  )
1494
1470
  }));
1495
- return {
1496
- ...report,
1497
- categories: sortedCategories,
1498
- plugins: sortedPlugins
1499
- };
1500
1471
  }
1501
1472
 
1502
1473
  // packages/utils/src/lib/verbose-utils.ts
@@ -1696,7 +1667,7 @@ function auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits)
1696
1667
 
1697
1668
  // packages/core/package.json
1698
1669
  var name = "@code-pushup/core";
1699
- var version = "0.8.24";
1670
+ var version = "0.8.25";
1700
1671
 
1701
1672
  // packages/core/src/lib/implementation/collect.ts
1702
1673
  async function collect(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/core",
3
- "version": "0.8.24",
3
+ "version": "0.8.25",
4
4
  "dependencies": {
5
5
  "@code-pushup/models": "*",
6
6
  "@code-pushup/utils": "*",