@code-pushup/utils 0.18.1 → 0.19.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/index.js CHANGED
@@ -1017,16 +1017,140 @@ function executeProcess(cfg) {
1017
1017
  });
1018
1018
  }
1019
1019
 
1020
+ // packages/utils/src/lib/transform.ts
1021
+ import { platform } from "node:os";
1022
+ function toArray(val) {
1023
+ return Array.isArray(val) ? val : [val];
1024
+ }
1025
+ function objectToKeys(obj) {
1026
+ return Object.keys(obj);
1027
+ }
1028
+ function objectToEntries(obj) {
1029
+ return Object.entries(obj);
1030
+ }
1031
+ function countOccurrences(values) {
1032
+ return values.reduce(
1033
+ (acc, value) => ({ ...acc, [value]: (acc[value] ?? 0) + 1 }),
1034
+ {}
1035
+ );
1036
+ }
1037
+ function distinct(array) {
1038
+ return [...new Set(array)];
1039
+ }
1040
+ function deepClone(obj) {
1041
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1042
+ }
1043
+ function factorOf(items, filterFn) {
1044
+ const itemCount = items.length;
1045
+ if (!itemCount) {
1046
+ return 1;
1047
+ }
1048
+ const filterCount = items.filter(filterFn).length;
1049
+ return filterCount === 0 ? 1 : (itemCount - filterCount) / itemCount;
1050
+ }
1051
+ function objectToCliArgs(params) {
1052
+ if (!params) {
1053
+ return [];
1054
+ }
1055
+ return Object.entries(params).flatMap(([key, value]) => {
1056
+ if (key === "_") {
1057
+ return Array.isArray(value) ? value : [`${value}`];
1058
+ }
1059
+ const prefix = key.length === 1 ? "-" : "--";
1060
+ if (Array.isArray(value)) {
1061
+ return value.map((v) => `${prefix}${key}="${v}"`);
1062
+ }
1063
+ if (Array.isArray(value)) {
1064
+ return value.map((v) => `${prefix}${key}="${v}"`);
1065
+ }
1066
+ if (typeof value === "string") {
1067
+ return [`${prefix}${key}="${value}"`];
1068
+ }
1069
+ if (typeof value === "number") {
1070
+ return [`${prefix}${key}=${value}`];
1071
+ }
1072
+ if (typeof value === "boolean") {
1073
+ return [`${prefix}${value ? "" : "no-"}${key}`];
1074
+ }
1075
+ throw new Error(`Unsupported type ${typeof value} for key ${key}`);
1076
+ });
1077
+ }
1078
+ function toUnixPath(path) {
1079
+ return path.replace(/\\/g, "/");
1080
+ }
1081
+ function toUnixNewlines(text) {
1082
+ return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
1083
+ }
1084
+ function capitalize(text) {
1085
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
1086
+ 1
1087
+ )}`;
1088
+ }
1089
+ function toNumberPrecision(value, decimalPlaces) {
1090
+ return Number(
1091
+ `${Math.round(
1092
+ Number.parseFloat(`${value}e${decimalPlaces}`)
1093
+ )}e-${decimalPlaces}`
1094
+ );
1095
+ }
1096
+ function toOrdinal(value) {
1097
+ if (value % 10 === 1 && value % 100 !== 11) {
1098
+ return `${value}st`;
1099
+ }
1100
+ if (value % 10 === 2 && value % 100 !== 12) {
1101
+ return `${value}nd`;
1102
+ }
1103
+ if (value % 10 === 3 && value % 100 !== 13) {
1104
+ return `${value}rd`;
1105
+ }
1106
+ return `${value}th`;
1107
+ }
1108
+
1109
+ // packages/utils/src/lib/filter-by-slug.ts
1110
+ function filterGroupsByAuditSlug(groups, auditSlugs) {
1111
+ const slugs = toArray(auditSlugs);
1112
+ if (slugs.length === 0) {
1113
+ return groups;
1114
+ }
1115
+ return groups.map((group) => ({
1116
+ ...group,
1117
+ refs: filterSlug(group.refs, slugs)
1118
+ })).filter((group) => group.refs.length);
1119
+ }
1120
+ function filterAuditsBySlug(list, auditSlugs) {
1121
+ const slugs = toArray(auditSlugs);
1122
+ if (slugs.length === 0) {
1123
+ return list;
1124
+ }
1125
+ return filterSlug(list, slugs);
1126
+ }
1127
+ function filterSlug(refs, slugOrSlugs) {
1128
+ const slugs = toArray(slugOrSlugs);
1129
+ return refs.filter(({ slug }) => slugs.includes(slug));
1130
+ }
1131
+
1020
1132
  // packages/utils/src/lib/git.ts
1133
+ import { isAbsolute, join as join3, relative } from "node:path";
1021
1134
  import { simpleGit } from "simple-git";
1022
- var git = simpleGit();
1023
- async function getLatestCommit() {
1135
+ async function getLatestCommit(git = simpleGit()) {
1024
1136
  const log = await git.log({
1025
1137
  maxCount: 1,
1026
1138
  format: { hash: "%H", message: "%s", author: "%an", date: "%ad" }
1027
1139
  });
1028
1140
  return log.latest;
1029
1141
  }
1142
+ function getGitRoot(git = simpleGit()) {
1143
+ return git.revparse("--show-toplevel");
1144
+ }
1145
+ function formatGitPath(path, gitRoot) {
1146
+ const absolutePath = isAbsolute(path) ? path : join3(process.cwd(), path);
1147
+ const relativePath = relative(gitRoot, absolutePath);
1148
+ return toUnixPath(relativePath);
1149
+ }
1150
+ async function toGitPath(path, git = simpleGit()) {
1151
+ const gitRoot = await getGitRoot(git);
1152
+ return formatGitPath(path, gitRoot);
1153
+ }
1030
1154
  function validateCommitData(commitData, options = {}) {
1031
1155
  const { throwError = false } = options;
1032
1156
  if (!commitData) {
@@ -1049,18 +1173,24 @@ function groupByStatus(results) {
1049
1173
  );
1050
1174
  }
1051
1175
 
1052
- // packages/utils/src/lib/progress.ts
1176
+ // packages/utils/src/lib/logging.ts
1053
1177
  import chalk2 from "chalk";
1178
+ function link(text) {
1179
+ return chalk2.underline(chalk2.blueBright(text));
1180
+ }
1181
+
1182
+ // packages/utils/src/lib/progress.ts
1183
+ import chalk3 from "chalk";
1054
1184
  import { MultiProgressBars } from "multi-progress-bars";
1055
1185
  var barStyles = {
1056
- active: (s) => chalk2.green(s),
1057
- done: (s) => chalk2.gray(s),
1058
- idle: (s) => chalk2.gray(s)
1186
+ active: (s) => chalk3.green(s),
1187
+ done: (s) => chalk3.gray(s),
1188
+ idle: (s) => chalk3.gray(s)
1059
1189
  };
1060
1190
  var messageStyles = {
1061
- active: (s) => chalk2.black(s),
1062
- done: (s) => chalk2.green(chalk2.bold(s)),
1063
- idle: (s) => chalk2.gray(s)
1191
+ active: (s) => chalk3.black(s),
1192
+ done: (s) => chalk3.green(chalk3.bold(s)),
1193
+ idle: (s) => chalk3.gray(s)
1064
1194
  };
1065
1195
  var mpb;
1066
1196
  function getSingletonProgressBars(options) {
@@ -1140,7 +1270,7 @@ function h3(text) {
1140
1270
  }
1141
1271
 
1142
1272
  // packages/utils/src/lib/reports/md/link.ts
1143
- function link(href, text) {
1273
+ function link2(href, text) {
1144
1274
  return `[${text || href}](${href})`;
1145
1275
  }
1146
1276
 
@@ -1191,7 +1321,7 @@ function generateMdReport(report, commitData) {
1191
1321
  (printCategories ? reportToCategoriesSection(report) + NEW_LINE + NEW_LINE : "") + // audits section
1192
1322
  reportToAuditsSection(report) + NEW_LINE + NEW_LINE + // about section
1193
1323
  reportToAboutSection(report, commitData) + NEW_LINE + NEW_LINE + // footer section
1194
- `${FOOTER_PREFIX} ${link(README_LINK, "Code PushUp")}`
1324
+ `${FOOTER_PREFIX} ${link2(README_LINK, "Code PushUp")}`
1195
1325
  );
1196
1326
  }
1197
1327
  function reportToHeaderSection() {
@@ -1202,7 +1332,7 @@ function reportToOverviewSection(report) {
1202
1332
  const tableContent = [
1203
1333
  reportOverviewTableHeaders,
1204
1334
  ...categories.map(({ title, refs, score }) => [
1205
- link(`#${slugify(title)}`, title),
1335
+ link2(`#${slugify(title)}`, title),
1206
1336
  `${getRoundScoreMarker(score)} ${style(formatReportScore(score))}`,
1207
1337
  countCategoryAudits(refs, plugins).toString()
1208
1338
  ])
@@ -1234,7 +1364,7 @@ function reportToCategoriesSection(report) {
1234
1364
  }
1235
1365
  function auditItemToCategorySection(audit, plugins) {
1236
1366
  const pluginTitle = getPluginNameFromSlug(audit.plugin, plugins);
1237
- const auditTitle = link(
1367
+ const auditTitle = link2(
1238
1368
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1239
1369
  audit.title
1240
1370
  );
@@ -1251,7 +1381,7 @@ function groupItemToCategorySection(group, plugins) {
1251
1381
  `${getRoundScoreMarker(groupScore)} ${group.title} (_${pluginTitle}_)`
1252
1382
  );
1253
1383
  const groupAudits = group.audits.reduce((acc, audit) => {
1254
- const auditTitle = link(
1384
+ const auditTitle = link2(
1255
1385
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1256
1386
  audit.title
1257
1387
  );
@@ -1338,7 +1468,7 @@ function getDocsAndDescription({
1338
1468
  description
1339
1469
  }) {
1340
1470
  if (docsUrl) {
1341
- const docsLink = link(docsUrl, "\u{1F4D6} Docs");
1471
+ const docsLink = link2(docsUrl, "\u{1F4D6} Docs");
1342
1472
  if (!description) {
1343
1473
  return docsLink + NEW_LINE + NEW_LINE;
1344
1474
  }
@@ -1359,7 +1489,7 @@ function getAuditResult(audit, isHtml = false) {
1359
1489
 
1360
1490
  // packages/utils/src/lib/reports/generate-stdout-summary.ts
1361
1491
  import cliui from "@isaacs/cliui";
1362
- import chalk3 from "chalk";
1492
+ import chalk4 from "chalk";
1363
1493
  import CliTable3 from "cli-table3";
1364
1494
  function addLine(line = "") {
1365
1495
  return line + NEW_LINE;
@@ -1370,7 +1500,7 @@ function generateStdoutSummary(report) {
1370
1500
  }
1371
1501
  function reportToHeaderSection2(report) {
1372
1502
  const { packageName, version } = report;
1373
- return `${chalk3.bold(reportHeadlineText)} - ${packageName}@${version}`;
1503
+ return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version}`;
1374
1504
  }
1375
1505
  function reportToDetailSection(report) {
1376
1506
  const { plugins } = report;
@@ -1390,13 +1520,13 @@ function reportToDetailSection(report) {
1390
1520
  padding: [0, 3, 0, 0]
1391
1521
  },
1392
1522
  {
1393
- text: chalk3.cyanBright(audit.displayValue || `${audit.value}`),
1523
+ text: chalk4.cyanBright(audit.displayValue || `${audit.value}`),
1394
1524
  width: 10,
1395
1525
  padding: [0, 0, 0, 0]
1396
1526
  }
1397
1527
  );
1398
1528
  });
1399
- return acc + addLine() + addLine(chalk3.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui.toString()) + addLine();
1529
+ return acc + addLine() + addLine(chalk4.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui.toString()) + addLine();
1400
1530
  }, "");
1401
1531
  }
1402
1532
  function reportToOverviewSection2({
@@ -1419,11 +1549,11 @@ function reportToOverviewSection2({
1419
1549
  countCategoryAudits(refs, plugins)
1420
1550
  ])
1421
1551
  );
1422
- return addLine(chalk3.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1552
+ return addLine(chalk4.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1423
1553
  }
1424
1554
  function withColor({ score, text }) {
1425
1555
  const formattedScore = text ?? formatReportScore(score);
1426
- const style2 = text ? chalk3 : chalk3.bold;
1556
+ const style2 = text ? chalk4 : chalk4.bold;
1427
1557
  if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
1428
1558
  return style2.green(formattedScore);
1429
1559
  }
@@ -1433,99 +1563,6 @@ function withColor({ score, text }) {
1433
1563
  return style2.red(formattedScore);
1434
1564
  }
1435
1565
 
1436
- // packages/utils/src/lib/transform.ts
1437
- import { platform } from "node:os";
1438
- function toArray(val) {
1439
- return Array.isArray(val) ? val : [val];
1440
- }
1441
- function objectToKeys(obj) {
1442
- return Object.keys(obj);
1443
- }
1444
- function objectToEntries(obj) {
1445
- return Object.entries(obj);
1446
- }
1447
- function countOccurrences(values) {
1448
- return values.reduce(
1449
- (acc, value) => ({ ...acc, [value]: (acc[value] ?? 0) + 1 }),
1450
- {}
1451
- );
1452
- }
1453
- function distinct(array) {
1454
- return [...new Set(array)];
1455
- }
1456
- function deepClone(obj) {
1457
- return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1458
- }
1459
- function factorOf(items, filterFn) {
1460
- const itemCount = items.length;
1461
- if (!itemCount) {
1462
- return 1;
1463
- }
1464
- const filterCount = items.filter(filterFn).length;
1465
- return filterCount === 0 ? 1 : (itemCount - filterCount) / itemCount;
1466
- }
1467
- function objectToCliArgs(params) {
1468
- if (!params) {
1469
- return [];
1470
- }
1471
- return Object.entries(params).flatMap(([key, value]) => {
1472
- if (key === "_") {
1473
- return Array.isArray(value) ? value : [`${value}`];
1474
- }
1475
- const prefix = key.length === 1 ? "-" : "--";
1476
- if (Array.isArray(value)) {
1477
- return value.map((v) => `${prefix}${key}="${v}"`);
1478
- }
1479
- if (Array.isArray(value)) {
1480
- return value.map((v) => `${prefix}${key}="${v}"`);
1481
- }
1482
- if (typeof value === "string") {
1483
- return [`${prefix}${key}="${value}"`];
1484
- }
1485
- if (typeof value === "number") {
1486
- return [`${prefix}${key}=${value}`];
1487
- }
1488
- if (typeof value === "boolean") {
1489
- return [`${prefix}${value ? "" : "no-"}${key}`];
1490
- }
1491
- throw new Error(`Unsupported type ${typeof value} for key ${key}`);
1492
- });
1493
- }
1494
- function toUnixPath(path, options) {
1495
- const unixPath = path.replace(/\\/g, "/");
1496
- if (options?.toRelative) {
1497
- return unixPath.replace(`${process.cwd().replace(/\\/g, "/")}/`, "");
1498
- }
1499
- return unixPath;
1500
- }
1501
- function toUnixNewlines(text) {
1502
- return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
1503
- }
1504
- function capitalize(text) {
1505
- return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
1506
- 1
1507
- )}`;
1508
- }
1509
- function toNumberPrecision(value, decimalPlaces) {
1510
- return Number(
1511
- `${Math.round(
1512
- Number.parseFloat(`${value}e${decimalPlaces}`)
1513
- )}e-${decimalPlaces}`
1514
- );
1515
- }
1516
- function toOrdinal(value) {
1517
- if (value % 10 === 1 && value % 100 !== 11) {
1518
- return `${value}st`;
1519
- }
1520
- if (value % 10 === 2 && value % 100 !== 12) {
1521
- return `${value}nd`;
1522
- }
1523
- if (value % 10 === 3 && value % 100 !== 13) {
1524
- return `${value}rd`;
1525
- }
1526
- return `${value}th`;
1527
- }
1528
-
1529
1566
  // packages/utils/src/lib/reports/scoring.ts
1530
1567
  var GroupRefInvalidError = class extends Error {
1531
1568
  constructor(auditSlug, pluginSlug) {
@@ -1685,35 +1722,6 @@ var verboseUtils = (verbose = false) => ({
1685
1722
  log: getLogVerbose(verbose),
1686
1723
  exec: getExecVerbose(verbose)
1687
1724
  });
1688
-
1689
- // packages/utils/src/lib/logging.ts
1690
- import chalk4 from "chalk";
1691
- function link2(text) {
1692
- return chalk4.underline(chalk4.blueBright(text));
1693
- }
1694
-
1695
- // packages/utils/src/lib/filter-by-slug.ts
1696
- function filterGroupsByAuditSlug(groups, auditSlugs) {
1697
- const slugs = toArray(auditSlugs);
1698
- if (slugs.length === 0) {
1699
- return groups;
1700
- }
1701
- return groups.map((group) => ({
1702
- ...group,
1703
- refs: filterSlug(group.refs, slugs)
1704
- })).filter((group) => group.refs.length);
1705
- }
1706
- function filterAuditsBySlug(list, auditSlugs) {
1707
- const slugs = toArray(auditSlugs);
1708
- if (slugs.length === 0) {
1709
- return list;
1710
- }
1711
- return filterSlug(list, slugs);
1712
- }
1713
- function filterSlug(refs, slugOrSlugs) {
1714
- const slugs = toArray(slugOrSlugs);
1715
- return refs.filter(({ slug }) => slugs.includes(slug));
1716
- }
1717
1725
  export {
1718
1726
  CODE_PUSHUP_DOMAIN,
1719
1727
  FOOTER_PREFIX,
@@ -1737,16 +1745,17 @@ export {
1737
1745
  findLineNumberInText,
1738
1746
  formatBytes,
1739
1747
  formatDuration,
1748
+ formatGitPath,
1740
1749
  generateMdReport,
1741
1750
  generateStdoutSummary,
1751
+ getGitRoot,
1742
1752
  getLatestCommit,
1743
1753
  getProgressBar,
1744
- git,
1745
1754
  groupByStatus,
1746
1755
  importEsmModule,
1747
1756
  isPromiseFulfilledResult,
1748
1757
  isPromiseRejectedResult,
1749
- link2 as link,
1758
+ link,
1750
1759
  loadReport,
1751
1760
  logMultipleFileResults,
1752
1761
  logMultipleResults,
@@ -1764,6 +1773,7 @@ export {
1764
1773
  slugify,
1765
1774
  sortReport,
1766
1775
  toArray,
1776
+ toGitPath,
1767
1777
  toNumberPrecision,
1768
1778
  toOrdinal,
1769
1779
  toUnixNewlines,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/utils",
3
- "version": "0.18.1",
3
+ "version": "0.19.0",
4
4
  "dependencies": {
5
5
  "@code-pushup/models": "*",
6
6
  "bundle-require": "^4.0.1",
package/src/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  export { exists } from '@code-pushup/models';
2
2
  export { ProcessConfig, ProcessError, ProcessObserver, ProcessResult, executeProcess, } from './lib/execute-process';
3
3
  export { CrawlFileSystemOptions, FileResult, MultipleFileResults, crawlFileSystem, directoryExists, ensureDirectoryExists, fileExists, findLineNumberInText, importEsmModule, logMultipleFileResults, pluginWorkDir, readJsonFile, readTextFile, removeDirectoryIfExists, } from './lib/file-system';
4
+ export { filterAuditsBySlug, filterGroupsByAuditSlug, } from './lib/filter-by-slug';
4
5
  export { formatBytes, formatDuration, pluralize, pluralizeToken, slugify, truncateDescription, truncateIssueMessage, truncateText, truncateTitle, } from './lib/formatting';
5
- export { getLatestCommit, git, validateCommitData } from './lib/git';
6
+ export { formatGitPath, getGitRoot, getLatestCommit, toGitPath, validateCommitData, } from './lib/git';
6
7
  export { groupByStatus } from './lib/group-by-status';
7
8
  export { isPromiseFulfilledResult, isPromiseRejectedResult, } from './lib/guards';
8
9
  export { logMultipleResults } from './lib/log-results';
10
+ export { link } from './lib/logging';
9
11
  export { ProgressBar, getProgressBar } from './lib/progress';
10
12
  export { TERMINAL_WIDTH } from './lib/reports/constants';
11
13
  export { generateMdReport } from './lib/reports/generate-md-report';
@@ -15,5 +17,3 @@ export { sortReport } from './lib/reports/sorting';
15
17
  export { CODE_PUSHUP_DOMAIN, FOOTER_PREFIX, README_LINK, calcDuration, compareIssueSeverity, loadReport, portalCommitDashboardLink, } from './lib/reports/utils';
16
18
  export { CliArgsObject, capitalize, countOccurrences, distinct, factorOf, objectToCliArgs, objectToEntries, objectToKeys, toArray, toNumberPrecision, toOrdinal, toUnixNewlines, toUnixPath, } from './lib/transform';
17
19
  export { verboseUtils } from './lib/verbose-utils';
18
- export { link } from './lib/logging';
19
- export { filterAuditsBySlug, filterGroupsByAuditSlug, } from './lib/filter-by-slug';
package/src/lib/git.d.ts CHANGED
@@ -4,13 +4,15 @@ export type CommitData = {
4
4
  author: string;
5
5
  date: string;
6
6
  };
7
- export declare const git: import("simple-git").SimpleGit;
8
- export declare function getLatestCommit(): Promise<({
7
+ export declare function getLatestCommit(git?: import("simple-git").SimpleGit): Promise<({
9
8
  hash: string;
10
9
  message: string;
11
10
  author: string;
12
11
  date: string;
13
12
  } & import("simple-git").ListLogLine) | null>;
14
- export declare function validateCommitData(commitData?: unknown, options?: {
13
+ export declare function getGitRoot(git?: import("simple-git").SimpleGit): Promise<string>;
14
+ export declare function formatGitPath(path: string, gitRoot: string): string;
15
+ export declare function toGitPath(path: string, git?: import("simple-git").SimpleGit): Promise<string>;
16
+ export declare function validateCommitData(commitData: CommitData | null, options?: {
15
17
  throwError?: boolean;
16
18
  }): commitData is CommitData;
@@ -22,9 +22,7 @@ Record<string, ArgumentValue | undefined> | {
22
22
  * });
23
23
  */
24
24
  export declare function objectToCliArgs<T extends object = Record<string, ArgumentValue>>(params?: CliArgsObject<T>): string[];
25
- export declare function toUnixPath(path: string, options?: {
26
- toRelative?: boolean;
27
- }): string;
25
+ export declare function toUnixPath(path: string): string;
28
26
  export declare function toUnixNewlines(text: string): string;
29
27
  export declare function capitalize<T extends string>(text: T): Capitalize<T>;
30
28
  export declare function toNumberPrecision(value: number, decimalPlaces: number): number;