@code-pushup/utils 0.35.0 → 0.39.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
@@ -574,10 +574,14 @@ function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
574
574
  { description }
575
575
  );
576
576
  }
577
- var scorableMetaSchema = z14.object({ slug: slugSchema, title: titleSchema });
577
+ var scorableMetaSchema = z14.object({
578
+ slug: slugSchema,
579
+ title: titleSchema,
580
+ docsUrl: docsUrlSchema
581
+ });
578
582
  var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
579
583
  z14.object({
580
- plugin: pluginMetaSchema.pick({ slug: true, title: true }).describe("Plugin which defines it")
584
+ plugin: pluginMetaSchema.pick({ slug: true, title: true, docsUrl: true }).describe("Plugin which defines it")
581
585
  })
582
586
  );
583
587
  var scorableDiffSchema = scorableMetaSchema.merge(
@@ -904,7 +908,7 @@ async function ensureDirectoryExists(baseDir) {
904
908
  await mkdir(baseDir, { recursive: true });
905
909
  return;
906
910
  } catch (error) {
907
- ui().logger.error(error.message);
911
+ ui().logger.info(error.message);
908
912
  if (error.code !== "EEXIST") {
909
913
  throw error;
910
914
  }
@@ -1440,11 +1444,9 @@ function toOrdinal(value) {
1440
1444
  async function getLatestCommit(git = simpleGit()) {
1441
1445
  const log2 = await git.log({
1442
1446
  maxCount: 1,
1447
+ // git log -1 --pretty=format:"%H %s %an %aI" - See: https://git-scm.com/docs/pretty-formats
1443
1448
  format: { hash: "%H", message: "%s", author: "%an", date: "%aI" }
1444
1449
  });
1445
- if (!log2.latest) {
1446
- return null;
1447
- }
1448
1450
  return commitSchema.parse(log2.latest);
1449
1451
  }
1450
1452
  function getGitRoot(git = simpleGit()) {
@@ -1459,25 +1461,48 @@ async function toGitPath(path, git = simpleGit()) {
1459
1461
  const gitRoot = await getGitRoot(git);
1460
1462
  return formatGitPath(path, gitRoot);
1461
1463
  }
1462
- async function guardAgainstLocalChanges(git = simpleGit()) {
1463
- const isClean = await git.status(["-s"]).then((r) => r.files.length === 0);
1464
- if (!isClean) {
1465
- throw new Error(
1466
- "Working directory needs to be clean before we you can proceed. Commit your local changes or stash them."
1464
+ var GitStatusError = class _GitStatusError extends Error {
1465
+ static ignoredProps = /* @__PURE__ */ new Set(["current", "tracking"]);
1466
+ static getReducedStatus(status) {
1467
+ return Object.fromEntries(
1468
+ Object.entries(status).filter(([key]) => !this.ignoredProps.has(key)).filter(
1469
+ (entry) => {
1470
+ const value = entry[1];
1471
+ if (value == null) {
1472
+ return false;
1473
+ }
1474
+ if (Array.isArray(value) && value.length === 0) {
1475
+ return false;
1476
+ }
1477
+ if (typeof value === "number" && value === 0) {
1478
+ return false;
1479
+ }
1480
+ return !(typeof value === "boolean" && !value);
1481
+ }
1482
+ )
1467
1483
  );
1468
1484
  }
1485
+ constructor(status) {
1486
+ super(
1487
+ `Working directory needs to be clean before we you can proceed. Commit your local changes or stash them:
1488
+ ${JSON.stringify(
1489
+ _GitStatusError.getReducedStatus(status),
1490
+ null,
1491
+ 2
1492
+ )}`
1493
+ );
1494
+ }
1495
+ };
1496
+ async function guardAgainstLocalChanges(git = simpleGit()) {
1497
+ const status = await git.status(["-s"]);
1498
+ if (status.files.length > 0) {
1499
+ throw new GitStatusError(status);
1500
+ }
1469
1501
  }
1470
1502
  async function getCurrentBranchOrTag(git = simpleGit()) {
1471
- try {
1472
- const branch = await git.branch().then((r) => r.current);
1473
- if (branch) {
1474
- return branch;
1475
- } else {
1476
- return await git.raw(["describe", "--tags", "--exact-match"]).then((out) => out.trim());
1477
- }
1478
- } catch {
1479
- throw new Error("Could not get current tag or branch.");
1480
- }
1503
+ return await git.branch().then((r) => r.current) || // If no current branch, try to get the tag
1504
+ // @TODO use simple git
1505
+ await git.raw(["describe", "--tags", "--exact-match"]).then((out) => out.trim());
1481
1506
  }
1482
1507
  async function safeCheckout(branchOrHash, forceCleanStatus = false, git = simpleGit()) {
1483
1508
  if (forceCleanStatus) {
@@ -1801,19 +1826,19 @@ function formatDiffCategoriesSection(diff) {
1801
1826
  "\u{1F504} Score change"
1802
1827
  ],
1803
1828
  ...sortChanges(changed).map((category) => [
1804
- category.title,
1829
+ formatTitle(category),
1805
1830
  formatScoreWithColor(category.scores.after),
1806
1831
  formatScoreWithColor(category.scores.before, { skipBold: true }),
1807
1832
  formatScoreChange(category.scores.diff)
1808
1833
  ]),
1809
1834
  ...added.map((category) => [
1810
- category.title,
1835
+ formatTitle(category),
1811
1836
  formatScoreWithColor(category.score),
1812
1837
  style("n/a (\\*)", ["i"]),
1813
1838
  style("n/a (\\*)", ["i"])
1814
1839
  ]),
1815
1840
  ...unchanged.map((category) => [
1816
- category.title,
1841
+ formatTitle(category),
1817
1842
  formatScoreWithColor(category.score),
1818
1843
  formatScoreWithColor(category.score, { skipBold: true }),
1819
1844
  "\u2013"
@@ -1839,8 +1864,8 @@ function formatDiffGroupsSection(diff) {
1839
1864
  "\u{1F504} Score change"
1840
1865
  ],
1841
1866
  rows: sortChanges(diff.groups.changed).map((group) => [
1842
- group.plugin.title,
1843
- group.title,
1867
+ formatTitle(group.plugin),
1868
+ formatTitle(group),
1844
1869
  formatScoreWithColor(group.scores.after),
1845
1870
  formatScoreWithColor(group.scores.before, { skipBold: true }),
1846
1871
  formatScoreChange(group.scores.diff)
@@ -1861,8 +1886,8 @@ function formatDiffAuditsSection(diff) {
1861
1886
  "\u{1F504} Value change"
1862
1887
  ],
1863
1888
  rows: sortChanges(diff.audits.changed).map((audit) => [
1864
- audit.plugin.title,
1865
- audit.title,
1889
+ formatTitle(audit.plugin),
1890
+ formatTitle(audit),
1866
1891
  `${getSquaredScoreMarker(audit.scores.after)} ${style(
1867
1892
  audit.displayValues.after || audit.values.after.toString()
1868
1893
  )}`,
@@ -1930,6 +1955,15 @@ function summarizeDiffOutcomes(outcomes, token) {
1930
1955
  }
1931
1956
  }).join(", ");
1932
1957
  }
1958
+ function formatTitle({
1959
+ title,
1960
+ docsUrl
1961
+ }) {
1962
+ if (docsUrl) {
1963
+ return link2(docsUrl, title);
1964
+ }
1965
+ return title;
1966
+ }
1933
1967
  function sortChanges(changes) {
1934
1968
  return [...changes].sort(
1935
1969
  (a, b) => Math.abs(b.scores.diff) - Math.abs(a.scores.diff) || Math.abs(b.values?.diff ?? 0) - Math.abs(a.values?.diff ?? 0)
@@ -2248,6 +2282,7 @@ export {
2248
2282
  getLatestCommit,
2249
2283
  getProgressBar,
2250
2284
  groupByStatus,
2285
+ guardAgainstLocalChanges,
2251
2286
  importEsmModule,
2252
2287
  isPromiseFulfilledResult,
2253
2288
  isPromiseRejectedResult,
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@code-pushup/utils",
3
- "version": "0.35.0",
3
+ "version": "0.39.0",
4
4
  "dependencies": {
5
- "@code-pushup/models": "0.35.0",
5
+ "@code-pushup/models": "0.39.0",
6
6
  "bundle-require": "^4.0.1",
7
+ "esbuild": "^0.19.2",
7
8
  "chalk": "^5.3.0",
8
9
  "@isaacs/cliui": "^8.0.2",
9
10
  "simple-git": "^3.20.0",
package/src/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
+ export { ExcludeNullFromPropertyTypes } from './lib/types';
1
2
  export { exists } from '@code-pushup/models';
2
3
  export { Diff, comparePairs, matchArrayItemsByKey } from './lib/diff';
3
4
  export { ProcessConfig, ProcessError, ProcessObserver, ProcessResult, executeProcess, } from './lib/execute-process';
4
5
  export { CrawlFileSystemOptions, FileResult, MultipleFileResults, crawlFileSystem, directoryExists, ensureDirectoryExists, fileExists, findLineNumberInText, importEsmModule, logMultipleFileResults, pluginWorkDir, readJsonFile, readTextFile, removeDirectoryIfExists, } from './lib/file-system';
5
6
  export { filterItemRefsBy } from './lib/filter';
6
7
  export { formatBytes, formatDuration, pluralize, pluralizeToken, slugify, truncateDescription, truncateIssueMessage, truncateText, truncateTitle, } from './lib/formatting';
7
- export { formatGitPath, getCurrentBranchOrTag, getGitRoot, getLatestCommit, safeCheckout, toGitPath, } from './lib/git';
8
+ export { formatGitPath, getCurrentBranchOrTag, guardAgainstLocalChanges, getGitRoot, getLatestCommit, safeCheckout, toGitPath, } from './lib/git';
8
9
  export { groupByStatus } from './lib/group-by-status';
9
10
  export { isPromiseFulfilledResult, isPromiseRejectedResult, } from './lib/guards';
10
11
  export { logMultipleResults } from './lib/log-results';
package/src/lib/git.d.ts CHANGED
@@ -1,8 +1,16 @@
1
+ import { StatusResult } from 'simple-git';
1
2
  import { Commit } from '@code-pushup/models';
2
3
  export declare function getLatestCommit(git?: import("simple-git").SimpleGit): Promise<Commit | null>;
3
4
  export declare function getGitRoot(git?: import("simple-git").SimpleGit): Promise<string>;
4
5
  export declare function formatGitPath(path: string, gitRoot: string): string;
5
6
  export declare function toGitPath(path: string, git?: import("simple-git").SimpleGit): Promise<string>;
7
+ export declare class GitStatusError extends Error {
8
+ static ignoredProps: Set<string>;
9
+ static getReducedStatus(status: StatusResult): {
10
+ [k: string]: any;
11
+ };
12
+ constructor(status: StatusResult);
13
+ }
6
14
  export declare function guardAgainstLocalChanges(git?: import("simple-git").SimpleGit): Promise<void>;
7
15
  export declare function getCurrentBranchOrTag(git?: import("simple-git").SimpleGit): Promise<string>;
8
16
  export declare function safeCheckout(branchOrHash: string, forceCleanStatus?: boolean, git?: import("simple-git").SimpleGit): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export type ExcludeNullFromPropertyTypes<T> = {
2
+ [P in keyof T]: Exclude<T[P], null>;
3
+ };