@code-pushup/utils 0.8.21 → 0.8.23

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/index.js CHANGED
@@ -558,7 +558,7 @@ function slugify(text) {
558
558
  }
559
559
  function pluralize(text) {
560
560
  if (text.endsWith("y")) {
561
- return text.slice(0, -1) + "ies";
561
+ return `${text.slice(0, -1)}ies`;
562
562
  }
563
563
  if (text.endsWith("s")) {
564
564
  return `${text}es`;
@@ -567,13 +567,14 @@ function pluralize(text) {
567
567
  }
568
568
  function formatBytes(bytes, decimals = 2) {
569
569
  bytes = Math.max(bytes, 0);
570
- if (!bytes)
570
+ if (!bytes) {
571
571
  return "0 B";
572
+ }
572
573
  const k = 1024;
573
574
  const dm = decimals < 0 ? 0 : decimals;
574
575
  const sizes = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
575
576
  const i = Math.floor(Math.log(bytes) / Math.log(k));
576
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
577
+ return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
577
578
  }
578
579
  function pluralizeToken(token, times = 0) {
579
580
  return `${times} ${Math.abs(times) === 1 ? token : pluralize(token)}`;
@@ -629,7 +630,7 @@ function logMultipleResults(results, messagePrefix, succeededCallback, failedCal
629
630
  }
630
631
  }
631
632
  function logPromiseResults(results, logMessage, callback) {
632
- if (results.length) {
633
+ if (results.length > 0) {
633
634
  if (results[0]?.status === "fulfilled") {
634
635
  console.info(logMessage);
635
636
  } else {
@@ -678,9 +679,8 @@ async function ensureDirectoryExists(baseDir) {
678
679
  function logMultipleFileResults(fileResults, messagePrefix) {
679
680
  const succeededCallback = (result) => {
680
681
  const [fileName, size] = result.value;
681
- console.info(
682
- `- ${chalk.bold(fileName)}` + (size ? ` (${chalk.gray(formatBytes(size))})` : "")
683
- );
682
+ const formattedSize = size ? ` (${chalk.gray(formatBytes(size))})` : "";
683
+ console.info(`- ${chalk.bold(fileName)}${formattedSize}`);
684
684
  };
685
685
  const failedCallback = (result) => {
686
686
  console.warn(`- ${chalk.bold(result.reason)}`);
@@ -738,6 +738,7 @@ function findLineNumberInText(content, pattern) {
738
738
  }
739
739
 
740
740
  // packages/utils/src/lib/reports/constants.ts
741
+ var TERMINAL_WIDTH = 80;
741
742
  var NEW_LINE = "\n";
742
743
  var SCORE_COLOR_RANGE = {
743
744
  GREEN_MIN: 0.9,
@@ -806,28 +807,20 @@ function getSeverityIcon(severity) {
806
807
  return "\u2139\uFE0F";
807
808
  }
808
809
  function calcDuration(start, stop) {
809
- stop = stop !== void 0 ? stop : performance.now();
810
+ stop ??= performance.now();
810
811
  return Math.floor(stop - start);
811
812
  }
812
813
  function countCategoryAudits(refs, plugins) {
813
814
  const groupLookup = plugins.reduce(
814
815
  (lookup, plugin) => {
815
- if (!plugin.groups.length) {
816
+ if (plugin.groups.length === 0) {
816
817
  return lookup;
817
818
  }
818
819
  return {
819
820
  ...lookup,
820
- [plugin.slug]: {
821
- ...plugin.groups.reduce(
822
- (groupLookup2, group) => {
823
- return {
824
- ...groupLookup2,
825
- [group.slug]: group
826
- };
827
- },
828
- {}
829
- )
830
- }
821
+ [plugin.slug]: Object.fromEntries(
822
+ plugin.groups.map((group) => [group.slug, group])
823
+ )
831
824
  };
832
825
  },
833
826
  {}
@@ -835,7 +828,7 @@ function countCategoryAudits(refs, plugins) {
835
828
  return refs.reduce((acc, ref) => {
836
829
  if (ref.type === "group") {
837
830
  const groupRefs = groupLookup[ref.plugin]?.[ref.slug]?.refs;
838
- return acc + (groupRefs?.length || 0);
831
+ return acc + (groupRefs?.length ?? 0);
839
832
  }
840
833
  return acc + 1;
841
834
  }, 0);
@@ -941,7 +934,7 @@ function compareIssues(a, b) {
941
934
  return 1;
942
935
  }
943
936
  if (a.source?.file !== b.source?.file) {
944
- return a.source?.file.localeCompare(b.source?.file || "") || 0;
937
+ return a.source?.file.localeCompare(b.source?.file || "") ?? 0;
945
938
  }
946
939
  if (!a.source?.position && b.source?.position) {
947
940
  return -1;
@@ -950,7 +943,7 @@ function compareIssues(a, b) {
950
943
  return 1;
951
944
  }
952
945
  if (a.source?.position?.startLine !== b.source?.position?.startLine) {
953
- return (a.source?.position?.startLine || 0) - (b.source?.position?.startLine || 0);
946
+ return (a.source?.position?.startLine ?? 0) - (b.source?.position?.startLine ?? 0);
954
947
  }
955
948
  return 0;
956
949
  }
@@ -968,12 +961,12 @@ var ProcessError = class extends Error {
968
961
  }
969
962
  };
970
963
  function executeProcess(cfg) {
971
- const { observer, cwd } = cfg;
972
- const { onStdout, onError, onComplete } = observer || {};
964
+ const { observer, cwd, command, args } = cfg;
965
+ const { onStdout, onError, onComplete } = observer ?? {};
973
966
  const date = (/* @__PURE__ */ new Date()).toISOString();
974
967
  const start = performance.now();
975
968
  return new Promise((resolve, reject) => {
976
- const process2 = spawn(cfg.command, cfg.args, { cwd, shell: true });
969
+ const process2 = spawn(command, args, { cwd, shell: true });
977
970
  let stdout = "";
978
971
  let stderr = "";
979
972
  process2.stdout.on("data", (data) => {
@@ -1107,7 +1100,7 @@ function style(text, styles = ["b"]) {
1107
1100
 
1108
1101
  // packages/utils/src/lib/reports/md/headline.ts
1109
1102
  function headline(text, hierarchy = 1) {
1110
- return `${new Array(hierarchy).fill("#").join("")} ${text}`;
1103
+ return `${"#".repeat(hierarchy)} ${text}`;
1111
1104
  }
1112
1105
  function h2(text) {
1113
1106
  return headline(text, 2);
@@ -1137,45 +1130,50 @@ function tableMd(data, align) {
1137
1130
  if (data.length === 0) {
1138
1131
  throw new Error("Data can't be empty");
1139
1132
  }
1140
- align = align || data[0]?.map(() => "c");
1141
- const _data = data.map((arr) => "|" + arr.join("|") + "|");
1142
- const secondRow = "|" + align?.map((s) => alignString.get(s)).join("|") + "|";
1143
- return _data.shift() + NEW_LINE + secondRow + NEW_LINE + _data.join(NEW_LINE);
1133
+ align ??= data[0]?.map(() => "c");
1134
+ const tableContent = data.map((arr) => `|${arr.join("|")}|`);
1135
+ const secondRow = `|${align?.map((s) => alignString.get(s)).join("|")}|`;
1136
+ return tableContent.shift() + NEW_LINE + secondRow + NEW_LINE + tableContent.join(NEW_LINE);
1144
1137
  }
1145
1138
  function tableHtml(data) {
1146
1139
  if (data.length === 0) {
1147
1140
  throw new Error("Data can't be empty");
1148
1141
  }
1149
- const _data = data.map((arr, index) => {
1142
+ const tableContent = data.map((arr, index) => {
1150
1143
  if (index === 0) {
1151
- return "<tr>" + arr.map((s) => `<th>${s}</th>`).join("") + "</tr>";
1144
+ const headerRow = arr.map((s) => `<th>${s}</th>`).join("");
1145
+ return `<tr>${headerRow}</tr>`;
1152
1146
  }
1153
- return "<tr>" + arr.map((s) => `<td>${s}</td>`).join("") + "</tr>";
1147
+ const row = arr.map((s) => `<td>${s}</td>`).join("");
1148
+ return `<tr>${row}</tr>`;
1154
1149
  });
1155
- return "<table>" + _data.join("") + "</table>";
1150
+ return `<table>${tableContent.join("")}</table>`;
1156
1151
  }
1157
1152
 
1158
1153
  // packages/utils/src/lib/reports/generate-md-report.ts
1159
1154
  function generateMdReport(report, commitData) {
1160
- let md = reportToHeaderSection() + NEW_LINE;
1161
- md += reportToOverviewSection(report) + NEW_LINE + NEW_LINE;
1162
- md += reportToCategoriesSection(report) + NEW_LINE + NEW_LINE;
1163
- md += reportToAuditsSection(report) + NEW_LINE + NEW_LINE;
1164
- md += reportToAboutSection(report, commitData) + NEW_LINE + NEW_LINE;
1165
- md += `${FOOTER_PREFIX} ${link(README_LINK, "Code PushUp")}`;
1166
- return md;
1155
+ return (
1156
+ // header section
1157
+ // eslint-disable-next-line prefer-template
1158
+ reportToHeaderSection() + NEW_LINE + // overview section
1159
+ reportToOverviewSection(report) + NEW_LINE + NEW_LINE + // categories section
1160
+ reportToCategoriesSection(report) + NEW_LINE + NEW_LINE + // audits section
1161
+ reportToAuditsSection(report) + NEW_LINE + NEW_LINE + // about section
1162
+ reportToAboutSection(report, commitData) + NEW_LINE + NEW_LINE + // footer section
1163
+ `${FOOTER_PREFIX} ${link(README_LINK, "Code PushUp")}`
1164
+ );
1167
1165
  }
1168
1166
  function reportToHeaderSection() {
1169
1167
  return headline(reportHeadlineText) + NEW_LINE;
1170
1168
  }
1171
1169
  function reportToOverviewSection(report) {
1172
- const { categories } = report;
1170
+ const { categories, plugins } = report;
1173
1171
  const tableContent = [
1174
1172
  reportOverviewTableHeaders,
1175
1173
  ...categories.map(({ title, refs, score }) => [
1176
1174
  link(`#${slugify(title)}`, title),
1177
1175
  `${getRoundScoreMarker(score)} ${style(formatReportScore(score))}`,
1178
- countCategoryAudits(refs, report.plugins).toString()
1176
+ countCategoryAudits(refs, plugins).toString()
1179
1177
  ])
1180
1178
  ];
1181
1179
  return tableMd(tableContent, ["l", "c", "c"]);
@@ -1311,7 +1309,10 @@ function reportToAboutSection(report, commitData) {
1311
1309
  formatDuration(duration2)
1312
1310
  ])
1313
1311
  ];
1314
- return h2("About") + NEW_LINE + NEW_LINE + `Report was created by [Code PushUp](${README_LINK}) on ${date}.` + NEW_LINE + NEW_LINE + tableMd(reportMetaTable, ["l", "c", "c", "c", "c", "c"]) + NEW_LINE + NEW_LINE + "The following plugins were run:" + NEW_LINE + NEW_LINE + tableMd(pluginMetaTable, ["l", "c", "c", "c"]);
1312
+ return (
1313
+ // eslint-disable-next-line prefer-template
1314
+ h2("About") + NEW_LINE + NEW_LINE + `Report was created by [Code PushUp](${README_LINK}) on ${date}.` + NEW_LINE + NEW_LINE + tableMd(reportMetaTable, ["l", "c", "c", "c", "c", "c"]) + NEW_LINE + NEW_LINE + "The following plugins were run:" + NEW_LINE + NEW_LINE + tableMd(pluginMetaTable, ["l", "c", "c", "c"])
1315
+ );
1315
1316
  }
1316
1317
  function getDocsAndDescription({
1317
1318
  docsUrl,
@@ -1345,13 +1346,7 @@ function addLine(line = "") {
1345
1346
  return line + NEW_LINE;
1346
1347
  }
1347
1348
  function generateStdoutSummary(report) {
1348
- let output = "";
1349
- output += addLine(reportToHeaderSection2(report));
1350
- output += addLine();
1351
- output += addLine(reportToDetailSection(report));
1352
- output += addLine(reportToOverviewSection2(report));
1353
- output += addLine(`${FOOTER_PREFIX} ${CODE_PUSHUP_DOMAIN}`);
1354
- return output;
1349
+ return addLine(reportToHeaderSection2(report)) + addLine() + addLine(reportToDetailSection(report)) + addLine(reportToOverviewSection2(report)) + addLine(`${FOOTER_PREFIX} ${CODE_PUSHUP_DOMAIN}`);
1355
1350
  }
1356
1351
  function reportToHeaderSection2(report) {
1357
1352
  const { packageName, version } = report;
@@ -1359,12 +1354,9 @@ function reportToHeaderSection2(report) {
1359
1354
  }
1360
1355
  function reportToDetailSection(report) {
1361
1356
  const { plugins } = report;
1362
- let output = "";
1363
- plugins.forEach(({ title, audits }) => {
1364
- output += addLine();
1365
- output += addLine(chalk3.magentaBright.bold(`${title} audits`));
1366
- output += addLine();
1367
- const ui = cliui({ width: 80 });
1357
+ return plugins.reduce((acc, plugin) => {
1358
+ const { title, audits } = plugin;
1359
+ const ui = cliui({ width: TERMINAL_WIDTH });
1368
1360
  audits.forEach(({ score, title: title2, displayValue, value }) => {
1369
1361
  ui.div(
1370
1362
  {
@@ -1374,6 +1366,7 @@ function reportToDetailSection(report) {
1374
1366
  },
1375
1367
  {
1376
1368
  text: title2,
1369
+ // eslint-disable-next-line no-magic-numbers
1377
1370
  padding: [0, 3, 0, 0]
1378
1371
  },
1379
1372
  {
@@ -1383,17 +1376,13 @@ function reportToDetailSection(report) {
1383
1376
  }
1384
1377
  );
1385
1378
  });
1386
- output += addLine(ui.toString());
1387
- output += addLine();
1388
- });
1389
- return output;
1379
+ return acc + addLine() + addLine(chalk3.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui.toString()) + addLine();
1380
+ }, "");
1390
1381
  }
1391
1382
  function reportToOverviewSection2({
1392
1383
  categories,
1393
1384
  plugins
1394
1385
  }) {
1395
- let output = addLine(chalk3.magentaBright.bold("Categories"));
1396
- output += addLine();
1397
1386
  const table = new Table({
1398
1387
  head: reportRawOverviewTableHeaders,
1399
1388
  colAligns: ["left", "right", "right"],
@@ -1408,8 +1397,7 @@ function reportToOverviewSection2({
1408
1397
  countCategoryAudits(refs, plugins)
1409
1398
  ])
1410
1399
  );
1411
- output += addLine(table.toString());
1412
- return output;
1400
+ return addLine(chalk3.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1413
1401
  }
1414
1402
  function withColor({ score, text }) {
1415
1403
  const formattedScore = text ?? formatReportScore(score);
@@ -1440,7 +1428,7 @@ function countOccurrences(values) {
1440
1428
  );
1441
1429
  }
1442
1430
  function distinct(array) {
1443
- return Array.from(new Set(array));
1431
+ return [...new Set(array)];
1444
1432
  }
1445
1433
  function deepClone(obj) {
1446
1434
  if (obj == null || typeof obj !== "object") {
@@ -1468,11 +1456,7 @@ function objectToCliArgs(params) {
1468
1456
  }
1469
1457
  return Object.entries(params).flatMap(([key, value]) => {
1470
1458
  if (key === "_") {
1471
- if (Array.isArray(value)) {
1472
- return value;
1473
- } else {
1474
- return [value + ""];
1475
- }
1459
+ return Array.isArray(value) ? value : [`${value}`];
1476
1460
  }
1477
1461
  const prefix = key.length === 1 ? "-" : "--";
1478
1462
  if (Array.isArray(value)) {
@@ -1496,7 +1480,7 @@ function objectToCliArgs(params) {
1496
1480
  function toUnixPath(path, options) {
1497
1481
  const unixPath = path.replace(/\\/g, "/");
1498
1482
  if (options?.toRelative) {
1499
- return unixPath.replace(process.cwd().replace(/\\/g, "/") + "/", "");
1483
+ return unixPath.replace(`${process.cwd().replace(/\\/g, "/")}/`, "");
1500
1484
  }
1501
1485
  return unixPath;
1502
1486
  }
@@ -1524,28 +1508,28 @@ function scoreReport(report) {
1524
1508
  const scoredReport = deepClone(report);
1525
1509
  const allScoredAuditsAndGroups = /* @__PURE__ */ new Map();
1526
1510
  scoredReport.plugins?.forEach((plugin) => {
1527
- const { audits } = plugin;
1511
+ const { slug, audits } = plugin;
1528
1512
  const groups = plugin.groups || [];
1529
1513
  audits.forEach((audit) => {
1530
- const key = `${plugin.slug}-${audit.slug}-audit`;
1531
- audit.plugin = plugin.slug;
1514
+ const key = `${slug}-${audit.slug}-audit`;
1515
+ audit.plugin = slug;
1532
1516
  allScoredAuditsAndGroups.set(key, audit);
1533
1517
  });
1534
1518
  function groupScoreFn(ref) {
1535
1519
  const score = allScoredAuditsAndGroups.get(
1536
- `${plugin.slug}-${ref.slug}-audit`
1520
+ `${slug}-${ref.slug}-audit`
1537
1521
  )?.score;
1538
1522
  if (score == null) {
1539
1523
  throw new Error(
1540
- `Group has invalid ref - audit with slug ${plugin.slug}-${ref.slug}-audit not found`
1524
+ `Group has invalid ref - audit with slug ${slug}-${ref.slug}-audit not found`
1541
1525
  );
1542
1526
  }
1543
1527
  return score;
1544
1528
  }
1545
1529
  groups.forEach((group) => {
1546
- const key = `${plugin.slug}-${group.slug}-group`;
1530
+ const key = `${slug}-${group.slug}-group`;
1547
1531
  group.score = calculateScore(group.refs, groupScoreFn);
1548
- group.plugin = plugin.slug;
1532
+ group.plugin = slug;
1549
1533
  allScoredAuditsAndGroups.set(key, group);
1550
1534
  });
1551
1535
  plugin.groups = groups;
@@ -1565,7 +1549,7 @@ function scoreReport(report) {
1565
1549
  category.score = calculateScore(category.refs, catScoreFn);
1566
1550
  scoredCategoriesMap.set(category.slug, category);
1567
1551
  }
1568
- scoredReport.categories = Array.from(scoredCategoriesMap.values());
1552
+ scoredReport.categories = [...scoredCategoriesMap.values()];
1569
1553
  return scoredReport;
1570
1554
  }
1571
1555
 
@@ -1591,7 +1575,7 @@ function sortReport(report) {
1591
1575
  ...groups,
1592
1576
  ...audits.sort(compareCategoryAudits)
1593
1577
  ];
1594
- const sortedRefs = category.refs.slice().sort((a, b) => {
1578
+ const sortedRefs = [...category.refs].sort((a, b) => {
1595
1579
  const aIndex = sortedAuditsAndGroups.findIndex(
1596
1580
  (ref) => ref.slug === a.slug
1597
1581
  );
@@ -1604,13 +1588,15 @@ function sortReport(report) {
1604
1588
  });
1605
1589
  const sortedPlugins = plugins.map((plugin) => ({
1606
1590
  ...plugin,
1607
- audits: plugin.audits.sort(compareAudits).map((audit) => ({
1608
- ...audit,
1609
- details: {
1610
- ...audit.details,
1611
- issues: audit?.details?.issues.slice().sort(compareIssues) || []
1612
- }
1613
- }))
1591
+ audits: [...plugin.audits].sort(compareAudits).map(
1592
+ (audit) => audit.details?.issues ? {
1593
+ ...audit,
1594
+ details: {
1595
+ ...audit.details,
1596
+ issues: [...audit.details.issues].sort(compareIssues)
1597
+ }
1598
+ } : audit
1599
+ )
1614
1600
  }));
1615
1601
  return {
1616
1602
  ...report,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/utils",
3
- "version": "0.8.21",
3
+ "version": "0.8.23",
4
4
  "dependencies": {
5
5
  "@code-pushup/models": "*",
6
6
  "bundle-require": "^4.0.1",
@@ -1,3 +1,4 @@
1
+ export declare const TERMINAL_WIDTH = 80;
1
2
  export declare const NEW_LINE = "\n";
2
3
  export declare const SCORE_COLOR_RANGE: {
3
4
  GREEN_MIN: number;
@@ -6,7 +6,8 @@ export declare function distinct<T extends string | number | boolean>(array: T[]
6
6
  export declare function deepClone<T>(obj: T): T;
7
7
  export declare function factorOf<T>(items: T[], filterFn: (i: T) => boolean): number;
8
8
  type ArgumentValue = number | string | boolean | string[];
9
- export type CliArgsObject<T extends object = Record<string, ArgumentValue>> = T extends never ? Record<string, ArgumentValue | undefined> | {
9
+ export type CliArgsObject<T extends object = Record<string, ArgumentValue>> = T extends never ? // eslint-disable-next-line @typescript-eslint/naming-convention
10
+ Record<string, ArgumentValue | undefined> | {
10
11
  _: string;
11
12
  } : T;
12
13
  /**