@code-pushup/core 0.8.13 → 0.8.15

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
@@ -1,6 +1,5 @@
1
1
  // packages/core/src/lib/implementation/persist.ts
2
- import { existsSync, mkdirSync } from "node:fs";
3
- import { stat as stat2, writeFile } from "node:fs/promises";
2
+ import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
4
3
  import { join as join2 } from "node:path";
5
4
 
6
5
  // packages/utils/src/lib/execute-process.ts
@@ -648,6 +647,14 @@ async function fileExists(path) {
648
647
  return false;
649
648
  }
650
649
  }
650
+ async function directoryExists(path) {
651
+ try {
652
+ const stats = await stat(path);
653
+ return stats.isDirectory();
654
+ } catch {
655
+ return false;
656
+ }
657
+ }
651
658
  async function ensureDirectoryExists(baseDir) {
652
659
  try {
653
660
  await mkdir(baseDir, { recursive: true });
@@ -1379,6 +1386,9 @@ function withColor({ score, text }) {
1379
1386
  }
1380
1387
 
1381
1388
  // packages/utils/src/lib/transform.ts
1389
+ function toArray(val) {
1390
+ return Array.isArray(val) ? val : [val];
1391
+ }
1382
1392
  function deepClone(obj) {
1383
1393
  if (obj == null || typeof obj !== "object") {
1384
1394
  return obj;
@@ -1545,47 +1555,55 @@ async function persistReport(report, options) {
1545
1555
  const { outputDir, filename, format } = options;
1546
1556
  const sortedScoredReport = sortReport(scoreReport(report));
1547
1557
  console.info(generateStdoutSummary(sortedScoredReport));
1548
- const results = [];
1549
- if (format.includes("json")) {
1550
- results.push({
1551
- format: "json",
1552
- content: JSON.stringify(report, null, 2)
1553
- });
1554
- }
1555
- if (format.includes("md")) {
1556
- const commitData = await getLatestCommit();
1557
- validateCommitData(commitData);
1558
- results.push({
1559
- format: "md",
1560
- content: generateMdReport(sortedScoredReport, commitData)
1561
- });
1562
- }
1563
- if (!existsSync(outputDir)) {
1558
+ const results = await Promise.all(
1559
+ format.map(async (reportType) => {
1560
+ switch (reportType) {
1561
+ case "json":
1562
+ return {
1563
+ format: "json",
1564
+ content: JSON.stringify(report, null, 2)
1565
+ };
1566
+ case "md":
1567
+ const commitData = await getLatestCommit();
1568
+ validateCommitData(commitData);
1569
+ return {
1570
+ format: "md",
1571
+ content: generateMdReport(sortedScoredReport, commitData)
1572
+ };
1573
+ }
1574
+ })
1575
+ );
1576
+ if (!await directoryExists(outputDir)) {
1564
1577
  try {
1565
- mkdirSync(outputDir, { recursive: true });
1566
- } catch (e) {
1567
- console.warn(e);
1578
+ await mkdir2(outputDir, { recursive: true });
1579
+ } catch (error) {
1580
+ console.warn(error);
1568
1581
  throw new PersistDirError(outputDir);
1569
1582
  }
1570
1583
  }
1571
1584
  return Promise.allSettled(
1572
- results.map(({ format: format2, content }) => {
1573
- const reportPath = join2(outputDir, `${filename}.${format2}`);
1574
- return writeFile(reportPath, content).then(() => stat2(reportPath)).then((stats) => [reportPath, stats.size]).catch((e) => {
1575
- console.warn(e);
1576
- throw new PersistError(reportPath);
1577
- });
1578
- })
1585
+ results.map(
1586
+ (result) => persistResult(
1587
+ join2(outputDir, `${filename}.${result.format}`),
1588
+ result.content
1589
+ )
1590
+ )
1579
1591
  );
1580
1592
  }
1581
- function logPersistedResults(persistResults) {
1582
- logMultipleFileResults(persistResults, "Generated reports");
1583
- }
1584
1593
  function validateCommitData(commitData) {
1585
1594
  if (!commitData) {
1586
1595
  console.warn("no commit data available");
1587
1596
  }
1588
1597
  }
1598
+ async function persistResult(reportPath, content) {
1599
+ return writeFile(reportPath, content).then(() => stat2(reportPath)).then((stats) => [reportPath, stats.size]).catch((error) => {
1600
+ console.warn(error);
1601
+ throw new PersistError(reportPath);
1602
+ });
1603
+ }
1604
+ function logPersistedResults(persistResults) {
1605
+ logMultipleFileResults(persistResults, "Generated reports");
1606
+ }
1589
1607
 
1590
1608
  // packages/core/src/lib/implementation/execute-plugin.ts
1591
1609
  import chalk4 from "chalk";
@@ -1599,12 +1617,8 @@ async function executeRunnerConfig(cfg, onProgress) {
1599
1617
  args,
1600
1618
  observer: { onStdout: onProgress }
1601
1619
  });
1602
- let audits = await readJsonFile(
1603
- join3(process.cwd(), outputFile)
1604
- );
1605
- if (outputTransform) {
1606
- audits = await outputTransform(audits);
1607
- }
1620
+ const outputs = await readJsonFile(join3(process.cwd(), outputFile));
1621
+ const audits = outputTransform ? await outputTransform(outputs) : outputs;
1608
1622
  return {
1609
1623
  duration,
1610
1624
  date,
@@ -1659,30 +1673,31 @@ async function executePlugin(pluginConfig, onProgress) {
1659
1673
  };
1660
1674
  }
1661
1675
  async function executePlugins(plugins, options) {
1662
- const { progress = false } = options || {};
1663
- const progressName = "Run Plugins";
1664
- const progressBar = progress ? getProgressBar(progressName) : null;
1676
+ const { progress = false } = options ?? {};
1677
+ const progressBar = progress ? getProgressBar("Run plugins") : null;
1665
1678
  const pluginsResult = await plugins.reduce(async (acc, pluginCfg) => {
1666
- const outputs = await acc;
1667
- progressBar?.updateTitle(`Executing ${chalk4.bold(pluginCfg.title)}`);
1679
+ progressBar?.updateTitle(`Executing ${chalk4.bold(pluginCfg.title)}`);
1668
1680
  try {
1669
1681
  const pluginReport = await executePlugin(pluginCfg);
1670
1682
  progressBar?.incrementInSteps(plugins.length);
1671
- return outputs.concat(Promise.resolve(pluginReport));
1672
- } catch (e) {
1683
+ return [...await acc, Promise.resolve(pluginReport)];
1684
+ } catch (error) {
1673
1685
  progressBar?.incrementInSteps(plugins.length);
1674
- return outputs.concat(
1675
- Promise.reject(e instanceof Error ? e.message : String(e))
1676
- );
1686
+ return [
1687
+ ...await acc,
1688
+ Promise.reject(error instanceof Error ? error.message : String(error))
1689
+ ];
1677
1690
  }
1678
1691
  }, Promise.resolve([]));
1679
1692
  progressBar?.endProgress("Done running plugins");
1680
- const errorsCallback = ({ reason }) => console.error(reason);
1693
+ const errorsCallback = ({ reason }) => {
1694
+ console.error(reason);
1695
+ };
1681
1696
  const results = await Promise.allSettled(pluginsResult);
1682
1697
  logMultipleResults(results, "Plugins", void 0, errorsCallback);
1683
1698
  const { fulfilled, rejected } = groupByStatus(results);
1684
- if (rejected.length) {
1685
- const errorMessages = rejected.map(({ reason }) => reason).join(", ");
1699
+ if (rejected.length > 0) {
1700
+ const errorMessages = rejected.map(({ reason }) => String(reason)).join(", ");
1686
1701
  throw new Error(
1687
1702
  `Plugins failed: ${rejected.length} errors: ${errorMessages}`
1688
1703
  );
@@ -1702,14 +1717,11 @@ function auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits)
1702
1717
 
1703
1718
  // packages/core/package.json
1704
1719
  var name = "@code-pushup/core";
1705
- var version = "0.8.13";
1720
+ var version = "0.8.15";
1706
1721
 
1707
1722
  // packages/core/src/lib/implementation/collect.ts
1708
1723
  async function collect(options) {
1709
1724
  const { plugins, categories } = options;
1710
- if (!plugins?.length) {
1711
- throw new Error("No plugins registered");
1712
- }
1713
1725
  const date = (/* @__PURE__ */ new Date()).toISOString();
1714
1726
  const start = performance.now();
1715
1727
  const pluginOutputs = await executePlugins(plugins, options);
@@ -1732,62 +1744,74 @@ import {
1732
1744
  IssueSourceType,
1733
1745
  IssueSeverity as PortalIssueSeverity
1734
1746
  } from "@code-pushup/portal-client";
1735
- function jsonToGql(report) {
1747
+ function jsonReportToGql(report) {
1736
1748
  return {
1737
1749
  packageName: report.packageName,
1738
1750
  packageVersion: report.version,
1739
1751
  commandStartDate: report.date,
1740
1752
  commandDuration: report.duration,
1741
- plugins: report.plugins.map((plugin) => ({
1742
- audits: plugin.audits.map((audit) => ({
1743
- description: audit.description,
1744
- details: {
1745
- issues: audit.details?.issues.map((issue) => ({
1746
- message: issue.message,
1747
- severity: transformSeverity(issue.severity),
1748
- sourceEndColumn: issue.source?.position?.endColumn,
1749
- sourceEndLine: issue.source?.position?.endLine,
1750
- sourceFilePath: issue.source?.file,
1751
- sourceStartColumn: issue.source?.position?.startColumn,
1752
- sourceStartLine: issue.source?.position?.startLine,
1753
- sourceType: IssueSourceType.SourceCode
1754
- })) || []
1755
- },
1756
- docsUrl: audit.docsUrl,
1757
- formattedValue: audit.displayValue,
1758
- score: audit.score,
1759
- slug: audit.slug,
1760
- title: audit.title,
1761
- value: audit.value
1762
- })),
1763
- description: plugin.description,
1764
- docsUrl: plugin.docsUrl,
1765
- groups: plugin.groups?.map((group) => ({
1766
- slug: group.slug,
1767
- title: group.title,
1768
- description: group.description,
1769
- refs: group.refs.map((ref) => ({ slug: ref.slug, weight: ref.weight }))
1770
- })),
1771
- icon: plugin.icon,
1772
- slug: plugin.slug,
1773
- title: plugin.title,
1774
- packageName: plugin.packageName,
1775
- packageVersion: plugin.version,
1776
- runnerDuration: plugin.duration,
1777
- runnerStartDate: plugin.date
1753
+ plugins: pluginReportsToGql(report.plugins),
1754
+ categories: categoryConfigsToGql(toArray(report.categories))
1755
+ };
1756
+ }
1757
+ function pluginReportsToGql(plugins) {
1758
+ return plugins.map((plugin) => ({
1759
+ audits: auditReportsToGql(plugin.audits),
1760
+ description: plugin.description,
1761
+ docsUrl: plugin.docsUrl,
1762
+ groups: plugin.groups?.map((group) => ({
1763
+ slug: group.slug,
1764
+ title: group.title,
1765
+ description: group.description,
1766
+ refs: group.refs.map((ref) => ({ slug: ref.slug, weight: ref.weight }))
1778
1767
  })),
1779
- categories: report.categories.map((category) => ({
1780
- slug: category.slug,
1781
- title: category.title,
1782
- description: category.description,
1783
- refs: category.refs.map((ref) => ({
1784
- plugin: ref.plugin,
1785
- type: ref.type === "audit" ? CategoryConfigRefType.Audit : CategoryConfigRefType.Group,
1786
- weight: ref.weight,
1787
- slug: ref.slug
1788
- }))
1768
+ icon: plugin.icon,
1769
+ slug: plugin.slug,
1770
+ title: plugin.title,
1771
+ packageName: plugin.packageName,
1772
+ packageVersion: plugin.version,
1773
+ runnerDuration: plugin.duration,
1774
+ runnerStartDate: plugin.date
1775
+ }));
1776
+ }
1777
+ function auditReportsToGql(audits) {
1778
+ return audits.map((audit) => ({
1779
+ description: audit.description,
1780
+ details: {
1781
+ issues: issuesToGql(audit.details?.issues)
1782
+ },
1783
+ docsUrl: audit.docsUrl,
1784
+ formattedValue: audit.displayValue,
1785
+ score: audit.score,
1786
+ slug: audit.slug,
1787
+ title: audit.title,
1788
+ value: audit.value
1789
+ }));
1790
+ }
1791
+ function issuesToGql(issues) {
1792
+ return issues?.map((issue) => ({
1793
+ message: issue.message,
1794
+ severity: transformSeverity(issue.severity),
1795
+ sourceEndColumn: issue.source?.position?.endColumn,
1796
+ sourceEndLine: issue.source?.position?.endLine,
1797
+ sourceFilePath: issue.source?.file,
1798
+ sourceStartColumn: issue.source?.position?.startColumn,
1799
+ sourceStartLine: issue.source?.position?.startLine,
1800
+ sourceType: IssueSourceType.SourceCode
1801
+ })) ?? [];
1802
+ }
1803
+ function categoryConfigsToGql(categories) {
1804
+ return categories.map((category) => ({
1805
+ slug: category.slug,
1806
+ title: category.title,
1807
+ description: category.description,
1808
+ refs: category.refs.map((ref) => ({
1809
+ plugin: ref.plugin,
1810
+ type: ref.type === "audit" ? CategoryConfigRefType.Audit : CategoryConfigRefType.Group,
1811
+ weight: ref.weight,
1812
+ slug: ref.slug
1789
1813
  }))
1790
- };
1814
+ }));
1791
1815
  }
1792
1816
  function transformSeverity(severity) {
1793
1817
  switch (severity) {
@@ -1810,8 +1834,8 @@ var normalizePersistConfig = (cfg) => ({
1810
1834
 
1811
1835
  // packages/core/src/lib/upload.ts
1812
1836
  async function upload(options, uploadFn = uploadToPortal) {
1813
- const persist = normalizePersistConfig(options?.persist);
1814
- if (!options?.upload) {
1837
+ const persist = normalizePersistConfig(options.persist);
1838
+ if (!options.upload) {
1815
1839
  throw new Error("upload config must be set");
1816
1840
  }
1817
1841
  const { apiKey, server, organization, project } = options.upload;
@@ -1827,7 +1851,7 @@ async function upload(options, uploadFn = uploadToPortal) {
1827
1851
  organization,
1828
1852
  project,
1829
1853
  commit: commitData.hash,
1830
- ...jsonToGql(report)
1854
+ ...jsonReportToGql(report)
1831
1855
  };
1832
1856
  return uploadFn({ apiKey, server, data });
1833
1857
  }
@@ -1836,9 +1860,11 @@ async function upload(options, uploadFn = uploadToPortal) {
1836
1860
  async function collectAndPersistReports(options) {
1837
1861
  const { exec } = verboseUtils(options.verbose);
1838
1862
  const report = await collect(options);
1839
- const persist = normalizePersistConfig(options?.persist);
1863
+ const persist = normalizePersistConfig(options.persist);
1840
1864
  const persistResults = await persistReport(report, persist);
1841
- exec(() => logPersistedResults(persistResults));
1865
+ exec(() => {
1866
+ logPersistedResults(persistResults);
1867
+ });
1842
1868
  report.plugins.forEach((plugin) => {
1843
1869
  pluginReportSchema.parse(plugin);
1844
1870
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/core",
3
- "version": "0.8.13",
3
+ "version": "0.8.15",
4
4
  "dependencies": {
5
5
  "@code-pushup/models": "*",
6
6
  "@code-pushup/utils": "*",
@@ -1,6 +1,6 @@
1
1
  import { CategoryConfigRefType, IssueSourceType, IssueSeverity as PortalIssueSeverity } from '@code-pushup/portal-client';
2
- import { Report } from '@code-pushup/models';
3
- export declare function jsonToGql(report: Report): {
2
+ import { Issue, Report } from '@code-pushup/models';
3
+ export declare function jsonReportToGql(report: Report): {
4
4
  packageName: string;
5
5
  packageVersion: string;
6
6
  commandStartDate: string;
@@ -58,3 +58,13 @@ export declare function jsonToGql(report: Report): {
58
58
  }[];
59
59
  }[];
60
60
  };
61
+ export declare function issuesToGql(issues: Issue[] | undefined): {
62
+ message: string;
63
+ severity: PortalIssueSeverity;
64
+ sourceEndColumn: number | undefined;
65
+ sourceEndLine: number | undefined;
66
+ sourceFilePath: string | undefined;
67
+ sourceStartColumn: number | undefined;
68
+ sourceStartLine: number | undefined;
69
+ sourceType: IssueSourceType;
70
+ }[];
@@ -1,8 +1,8 @@
1
- import { AuditOutputs, OnProgress, RunnerConfig, RunnerFunction } from '@code-pushup/models';
1
+ import { OnProgress, RunnerConfig, RunnerFunction } from '@code-pushup/models';
2
2
  export type RunnerResult = {
3
3
  date: string;
4
4
  duration: number;
5
- audits: AuditOutputs;
5
+ audits: unknown;
6
6
  };
7
7
  export declare function executeRunnerConfig(cfg: RunnerConfig, onProgress?: OnProgress): Promise<RunnerResult>;
8
8
  export declare function executeRunnerFunction(runner: RunnerFunction, onProgress?: OnProgress): Promise<RunnerResult>;