@code-pushup/cli 0.18.1 → 0.20.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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/index.js +152 -127
  3. package/package.json +3 -42
package/README.md CHANGED
@@ -147,6 +147,10 @@ jobs:
147
147
  - run: npx code-pushup autorun --upload.apiKey=${{ secrets.PORTAL_API_KEY }}
148
148
  ```
149
149
 
150
+ ## Configuration
151
+
152
+ For a comprehensive list of all options available in the config file, refer to [`CoreConfig` docs](../models/docs/models-reference.md#coreconfig).
153
+
150
154
  ## Custom Plugins
151
155
 
152
156
  We provide comprehensive documentation on [how to create a custom plugin](./docs/custom-plugins.md).
package/index.js CHANGED
@@ -83,25 +83,15 @@ function executionMetaSchema(options2 = {
83
83
  duration: z.number({ description: options2.descriptionDuration })
84
84
  });
85
85
  }
86
- function slugSchema(description = "Unique ID (human-readable, URL-safe)") {
87
- return z.string({ description }).regex(slugRegex, {
88
- message: "The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug"
89
- }).max(MAX_SLUG_LENGTH, {
90
- message: `slug can be max ${MAX_SLUG_LENGTH} characters long`
91
- });
92
- }
93
- function descriptionSchema(description = "Description (markdown)") {
94
- return z.string({ description }).max(MAX_DESCRIPTION_LENGTH).optional();
95
- }
96
- function docsUrlSchema(description = "Documentation site") {
97
- return urlSchema(description).optional().or(z.string().max(0));
98
- }
99
- function urlSchema(description) {
100
- return z.string({ description }).url();
101
- }
102
- function titleSchema(description = "Descriptive name") {
103
- return z.string({ description }).max(MAX_TITLE_LENGTH);
104
- }
86
+ var slugSchema = z.string({ description: "Unique ID (human-readable, URL-safe)" }).regex(slugRegex, {
87
+ message: "The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug"
88
+ }).max(MAX_SLUG_LENGTH, {
89
+ message: `slug can be max ${MAX_SLUG_LENGTH} characters long`
90
+ });
91
+ var descriptionSchema = z.string({ description: "Description (markdown)" }).max(MAX_DESCRIPTION_LENGTH).optional();
92
+ var urlSchema = z.string().url();
93
+ var docsUrlSchema = urlSchema.optional().or(z.literal("")).describe("Documentation site");
94
+ var titleSchema = z.string({ description: "Descriptive name" }).max(MAX_TITLE_LENGTH);
105
95
  function metaSchema(options2) {
106
96
  const {
107
97
  descriptionDescription,
@@ -111,24 +101,19 @@ function metaSchema(options2) {
111
101
  } = options2 ?? {};
112
102
  return z.object(
113
103
  {
114
- title: titleSchema(titleDescription),
115
- description: descriptionSchema(descriptionDescription),
116
- docsUrl: docsUrlSchema(docsUrlDescription)
104
+ title: titleDescription ? titleSchema.describe(titleDescription) : titleSchema,
105
+ description: descriptionDescription ? descriptionSchema.describe(descriptionDescription) : descriptionSchema,
106
+ docsUrl: docsUrlDescription ? docsUrlSchema.describe(docsUrlDescription) : docsUrlSchema
117
107
  },
118
108
  { description }
119
109
  );
120
110
  }
121
- function filePathSchema(description) {
122
- return z.string({ description }).trim().min(1, { message: "path is invalid" });
123
- }
124
- function fileNameSchema(description) {
125
- return z.string({ description }).trim().regex(filenameRegex, {
126
- message: `The filename has to be valid`
127
- }).min(1, { message: "file name is invalid" });
128
- }
129
- function positiveIntSchema(description) {
130
- return z.number({ description }).int().nonnegative();
131
- }
111
+ var filePathSchema = z.string().trim().min(1, { message: "path is invalid" });
112
+ var fileNameSchema = z.string().trim().regex(filenameRegex, {
113
+ message: `The filename has to be valid`
114
+ }).min(1, { message: "file name is invalid" });
115
+ var positiveIntSchema = z.number().int().positive();
116
+ var nonnegativeIntSchema = z.number().int().nonnegative();
132
117
  function packageVersionSchema(options2) {
133
118
  const { versionDescription = "NPM version of the package", required } = options2 ?? {};
134
119
  const packageSchema = z.string({ description: "NPM package name" });
@@ -141,14 +126,14 @@ function packageVersionSchema(options2) {
141
126
  { description: "NPM package name and version of a published package" }
142
127
  );
143
128
  }
144
- function weightSchema(description = "Coefficient for the given score (use weight 0 if only for display)") {
145
- return positiveIntSchema(description);
146
- }
129
+ var weightSchema = nonnegativeIntSchema.describe(
130
+ "Coefficient for the given score (use weight 0 if only for display)"
131
+ );
147
132
  function weightedRefSchema(description, slugDescription) {
148
133
  return z.object(
149
134
  {
150
- slug: slugSchema(slugDescription),
151
- weight: weightSchema("Weight used to calculate score")
135
+ slug: slugSchema.describe(slugDescription),
136
+ weight: weightSchema.describe("Weight used to calculate score")
152
137
  },
153
138
  { description }
154
139
  );
@@ -156,14 +141,14 @@ function weightedRefSchema(description, slugDescription) {
156
141
  function scorableSchema(description, refSchema, duplicateCheckFn, duplicateMessageFn) {
157
142
  return z.object(
158
143
  {
159
- slug: slugSchema('Human-readable unique ID, e.g. "performance"'),
144
+ slug: slugSchema.describe('Human-readable unique ID, e.g. "performance"'),
160
145
  refs: z.array(refSchema).min(1).refine(
161
146
  (refs) => !duplicateCheckFn(refs),
162
147
  (refs) => ({
163
148
  message: duplicateMessageFn(refs)
164
149
  })
165
- ).refine(hasWeightedRefsInCategories, () => ({
166
- message: `In a category there has to be at least one ref with weight > 0`
150
+ ).refine(hasNonZeroWeightedRef, () => ({
151
+ message: "In a category there has to be at least one ref with weight > 0"
167
152
  }))
168
153
  },
169
154
  { description }
@@ -172,13 +157,13 @@ function scorableSchema(description, refSchema, duplicateCheckFn, duplicateMessa
172
157
  var materialIconSchema = z.enum(MATERIAL_ICONS, {
173
158
  description: "Icon from VSCode Material Icons extension"
174
159
  });
175
- function hasWeightedRefsInCategories(categoryRefs) {
176
- return categoryRefs.reduce((acc, { weight }) => weight + acc, 0) !== 0;
160
+ function hasNonZeroWeightedRef(refs) {
161
+ return refs.reduce((acc, { weight }) => weight + acc, 0) !== 0;
177
162
  }
178
163
 
179
164
  // packages/models/src/lib/audit.ts
180
165
  var auditSchema = z2.object({
181
- slug: slugSchema("ID (unique within plugin)")
166
+ slug: slugSchema.describe("ID (unique within plugin)")
182
167
  }).merge(
183
168
  metaSchema({
184
169
  titleDescription: "Descriptive name",
@@ -205,17 +190,20 @@ function getDuplicateSlugsInAudits(audits) {
205
190
  return hasDuplicateStrings(audits.map(({ slug }) => slug));
206
191
  }
207
192
 
208
- // packages/models/src/lib/audit-issue.ts
193
+ // packages/models/src/lib/audit-output.ts
194
+ import { z as z4 } from "zod";
195
+
196
+ // packages/models/src/lib/issue.ts
209
197
  import { z as z3 } from "zod";
210
198
  var sourceFileLocationSchema = z3.object(
211
199
  {
212
- file: filePathSchema("Relative path to source file in Git repo"),
200
+ file: filePathSchema.describe("Relative path to source file in Git repo"),
213
201
  position: z3.object(
214
202
  {
215
- startLine: positiveIntSchema("Start line"),
216
- startColumn: positiveIntSchema("Start column").optional(),
217
- endLine: positiveIntSchema("End line").optional(),
218
- endColumn: positiveIntSchema("End column").optional()
203
+ startLine: positiveIntSchema.describe("Start line"),
204
+ startColumn: positiveIntSchema.describe("Start column").optional(),
205
+ endLine: positiveIntSchema.describe("End line").optional(),
206
+ endColumn: positiveIntSchema.describe("End column").optional()
219
207
  },
220
208
  { description: "Location in file" }
221
209
  ).optional()
@@ -235,21 +223,21 @@ var issueSchema = z3.object(
235
223
  );
236
224
 
237
225
  // packages/models/src/lib/audit-output.ts
238
- import { z as z4 } from "zod";
226
+ var auditDetailsSchema = z4.object(
227
+ {
228
+ issues: z4.array(issueSchema, { description: "List of findings" })
229
+ },
230
+ { description: "Detailed information" }
231
+ );
239
232
  var auditOutputSchema = z4.object(
240
233
  {
241
- slug: slugSchema("Reference to audit"),
234
+ slug: slugSchema.describe("Reference to audit"),
242
235
  displayValue: z4.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional(),
243
- value: positiveIntSchema("Raw numeric value"),
236
+ value: nonnegativeIntSchema.describe("Raw numeric value"),
244
237
  score: z4.number({
245
238
  description: "Value between 0 and 1"
246
239
  }).min(0).max(1),
247
- details: z4.object(
248
- {
249
- issues: z4.array(issueSchema, { description: "List of findings" })
250
- },
251
- { description: "Detailed information" }
252
- ).optional()
240
+ details: auditDetailsSchema.optional()
253
241
  },
254
242
  { description: "Audit information" }
255
243
  );
@@ -279,7 +267,7 @@ var categoryRefSchema = weightedRefSchema(
279
267
  type: z5.enum(["audit", "group"], {
280
268
  description: "Discriminant for reference kind, affects where `slug` is looked up"
281
269
  }),
282
- plugin: slugSchema(
270
+ plugin: slugSchema.describe(
283
271
  "Plugin slug (plugin should contain referenced audit or group)"
284
272
  )
285
273
  })
@@ -339,10 +327,8 @@ import { z as z11 } from "zod";
339
327
  import { z as z6 } from "zod";
340
328
  var formatSchema = z6.enum(["json", "md"]);
341
329
  var persistConfigSchema = z6.object({
342
- outputDir: filePathSchema("Artifacts folder").optional(),
343
- filename: fileNameSchema(
344
- "Artifacts file name (without extension)"
345
- ).optional(),
330
+ outputDir: filePathSchema.describe("Artifacts folder").optional(),
331
+ filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
346
332
  format: z6.array(formatSchema).optional()
347
333
  });
348
334
 
@@ -403,7 +389,7 @@ var runnerConfigSchema = z8.object(
403
389
  description: "Shell command to execute"
404
390
  }),
405
391
  args: z8.array(z8.string({ description: "Command arguments" })).optional(),
406
- outputFile: filePathSchema("Output path"),
392
+ outputFile: filePathSchema.describe("Output path"),
407
393
  outputTransform: outputTransformSchema.optional()
408
394
  },
409
395
  {
@@ -423,7 +409,7 @@ var pluginMetaSchema = packageVersionSchema().merge(
423
409
  })
424
410
  ).merge(
425
411
  z9.object({
426
- slug: slugSchema("Unique plugin slug within core config"),
412
+ slug: slugSchema.describe("Unique plugin slug within core config"),
427
413
  icon: materialIconSchema
428
414
  })
429
415
  );
@@ -456,12 +442,14 @@ function getMissingRefsFromGroups(pluginCfg) {
456
442
  // packages/models/src/lib/upload-config.ts
457
443
  import { z as z10 } from "zod";
458
444
  var uploadConfigSchema = z10.object({
459
- server: urlSchema("URL of deployed portal API"),
445
+ server: urlSchema.describe("URL of deployed portal API"),
460
446
  apiKey: z10.string({
461
447
  description: "API key with write access to portal (use `process.env` for security)"
462
448
  }),
463
- organization: slugSchema("Organization slug from Code PushUp portal"),
464
- project: slugSchema("Project slug from Code PushUp portal"),
449
+ organization: slugSchema.describe(
450
+ "Organization slug from Code PushUp portal"
451
+ ),
452
+ project: slugSchema.describe("Project slug from Code PushUp portal"),
465
453
  timeout: z10.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
466
454
  });
467
455
 
@@ -971,16 +959,35 @@ function executeProcess(cfg) {
971
959
  });
972
960
  }
973
961
 
962
+ // packages/utils/src/lib/transform.ts
963
+ function toArray(val) {
964
+ return Array.isArray(val) ? val : [val];
965
+ }
966
+ function deepClone(obj) {
967
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
968
+ }
969
+ function toUnixPath(path) {
970
+ return path.replace(/\\/g, "/");
971
+ }
972
+
974
973
  // packages/utils/src/lib/git.ts
974
+ import { isAbsolute, join as join2, relative } from "node:path";
975
975
  import { simpleGit } from "simple-git";
976
- var git = simpleGit();
977
- async function getLatestCommit() {
976
+ async function getLatestCommit(git = simpleGit()) {
978
977
  const log = await git.log({
979
978
  maxCount: 1,
980
979
  format: { hash: "%H", message: "%s", author: "%an", date: "%ad" }
981
980
  });
982
981
  return log.latest;
983
982
  }
983
+ function getGitRoot(git = simpleGit()) {
984
+ return git.revparse("--show-toplevel");
985
+ }
986
+ function formatGitPath(path, gitRoot) {
987
+ const absolutePath = isAbsolute(path) ? path : join2(process.cwd(), path);
988
+ const relativePath = relative(gitRoot, absolutePath);
989
+ return toUnixPath(relativePath);
990
+ }
984
991
  function validateCommitData(commitData, options2 = {}) {
985
992
  const { throwError = false } = options2;
986
993
  if (!commitData) {
@@ -1003,18 +1010,24 @@ function groupByStatus(results) {
1003
1010
  );
1004
1011
  }
1005
1012
 
1006
- // packages/utils/src/lib/progress.ts
1013
+ // packages/utils/src/lib/logging.ts
1007
1014
  import chalk2 from "chalk";
1015
+ function link(text) {
1016
+ return chalk2.underline(chalk2.blueBright(text));
1017
+ }
1018
+
1019
+ // packages/utils/src/lib/progress.ts
1020
+ import chalk3 from "chalk";
1008
1021
  import { MultiProgressBars } from "multi-progress-bars";
1009
1022
  var barStyles = {
1010
- active: (s) => chalk2.green(s),
1011
- done: (s) => chalk2.gray(s),
1012
- idle: (s) => chalk2.gray(s)
1023
+ active: (s) => chalk3.green(s),
1024
+ done: (s) => chalk3.gray(s),
1025
+ idle: (s) => chalk3.gray(s)
1013
1026
  };
1014
1027
  var messageStyles = {
1015
- active: (s) => chalk2.black(s),
1016
- done: (s) => chalk2.green(chalk2.bold(s)),
1017
- idle: (s) => chalk2.gray(s)
1028
+ active: (s) => chalk3.black(s),
1029
+ done: (s) => chalk3.green(chalk3.bold(s)),
1030
+ idle: (s) => chalk3.gray(s)
1018
1031
  };
1019
1032
  var mpb;
1020
1033
  function getSingletonProgressBars(options2) {
@@ -1094,7 +1107,7 @@ function h3(text) {
1094
1107
  }
1095
1108
 
1096
1109
  // packages/utils/src/lib/reports/md/link.ts
1097
- function link(href, text) {
1110
+ function link2(href, text) {
1098
1111
  return `[${text || href}](${href})`;
1099
1112
  }
1100
1113
 
@@ -1145,7 +1158,7 @@ function generateMdReport(report, commitData) {
1145
1158
  (printCategories ? reportToCategoriesSection(report) + NEW_LINE + NEW_LINE : "") + // audits section
1146
1159
  reportToAuditsSection(report) + NEW_LINE + NEW_LINE + // about section
1147
1160
  reportToAboutSection(report, commitData) + NEW_LINE + NEW_LINE + // footer section
1148
- `${FOOTER_PREFIX} ${link(README_LINK, "Code PushUp")}`
1161
+ `${FOOTER_PREFIX} ${link2(README_LINK, "Code PushUp")}`
1149
1162
  );
1150
1163
  }
1151
1164
  function reportToHeaderSection() {
@@ -1156,7 +1169,7 @@ function reportToOverviewSection(report) {
1156
1169
  const tableContent = [
1157
1170
  reportOverviewTableHeaders,
1158
1171
  ...categories.map(({ title, refs, score }) => [
1159
- link(`#${slugify(title)}`, title),
1172
+ link2(`#${slugify(title)}`, title),
1160
1173
  `${getRoundScoreMarker(score)} ${style(formatReportScore(score))}`,
1161
1174
  countCategoryAudits(refs, plugins).toString()
1162
1175
  ])
@@ -1188,7 +1201,7 @@ function reportToCategoriesSection(report) {
1188
1201
  }
1189
1202
  function auditItemToCategorySection(audit, plugins) {
1190
1203
  const pluginTitle = getPluginNameFromSlug(audit.plugin, plugins);
1191
- const auditTitle = link(
1204
+ const auditTitle = link2(
1192
1205
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1193
1206
  audit.title
1194
1207
  );
@@ -1205,7 +1218,7 @@ function groupItemToCategorySection(group, plugins) {
1205
1218
  `${getRoundScoreMarker(groupScore)} ${group.title} (_${pluginTitle}_)`
1206
1219
  );
1207
1220
  const groupAudits = group.audits.reduce((acc, audit) => {
1208
- const auditTitle = link(
1221
+ const auditTitle = link2(
1209
1222
  `#${slugify(audit.title)}-${slugify(pluginTitle)}`,
1210
1223
  audit.title
1211
1224
  );
@@ -1292,7 +1305,7 @@ function getDocsAndDescription({
1292
1305
  description
1293
1306
  }) {
1294
1307
  if (docsUrl) {
1295
- const docsLink = link(docsUrl, "\u{1F4D6} Docs");
1308
+ const docsLink = link2(docsUrl, "\u{1F4D6} Docs");
1296
1309
  if (!description) {
1297
1310
  return docsLink + NEW_LINE + NEW_LINE;
1298
1311
  }
@@ -1313,7 +1326,7 @@ function getAuditResult(audit, isHtml = false) {
1313
1326
 
1314
1327
  // packages/utils/src/lib/reports/generate-stdout-summary.ts
1315
1328
  import cliui from "@isaacs/cliui";
1316
- import chalk3 from "chalk";
1329
+ import chalk4 from "chalk";
1317
1330
  import CliTable3 from "cli-table3";
1318
1331
  function addLine(line = "") {
1319
1332
  return line + NEW_LINE;
@@ -1324,7 +1337,7 @@ function generateStdoutSummary(report) {
1324
1337
  }
1325
1338
  function reportToHeaderSection2(report) {
1326
1339
  const { packageName, version: version2 } = report;
1327
- return `${chalk3.bold(reportHeadlineText)} - ${packageName}@${version2}`;
1340
+ return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version2}`;
1328
1341
  }
1329
1342
  function reportToDetailSection(report) {
1330
1343
  const { plugins } = report;
@@ -1344,13 +1357,13 @@ function reportToDetailSection(report) {
1344
1357
  padding: [0, 3, 0, 0]
1345
1358
  },
1346
1359
  {
1347
- text: chalk3.cyanBright(audit.displayValue || `${audit.value}`),
1360
+ text: chalk4.cyanBright(audit.displayValue || `${audit.value}`),
1348
1361
  width: 10,
1349
1362
  padding: [0, 0, 0, 0]
1350
1363
  }
1351
1364
  );
1352
1365
  });
1353
- return acc + addLine() + addLine(chalk3.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui2.toString()) + addLine();
1366
+ return acc + addLine() + addLine(chalk4.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui2.toString()) + addLine();
1354
1367
  }, "");
1355
1368
  }
1356
1369
  function reportToOverviewSection2({
@@ -1373,11 +1386,11 @@ function reportToOverviewSection2({
1373
1386
  countCategoryAudits(refs, plugins)
1374
1387
  ])
1375
1388
  );
1376
- return addLine(chalk3.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1389
+ return addLine(chalk4.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1377
1390
  }
1378
1391
  function withColor({ score, text }) {
1379
1392
  const formattedScore = text ?? formatReportScore(score);
1380
- const style2 = text ? chalk3 : chalk3.bold;
1393
+ const style2 = text ? chalk4 : chalk4.bold;
1381
1394
  if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
1382
1395
  return style2.green(formattedScore);
1383
1396
  }
@@ -1387,14 +1400,6 @@ function withColor({ score, text }) {
1387
1400
  return style2.red(formattedScore);
1388
1401
  }
1389
1402
 
1390
- // packages/utils/src/lib/transform.ts
1391
- function toArray(val) {
1392
- return Array.isArray(val) ? val : [val];
1393
- }
1394
- function deepClone(obj) {
1395
- return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1396
- }
1397
-
1398
1403
  // packages/utils/src/lib/reports/scoring.ts
1399
1404
  var GroupRefInvalidError = class extends Error {
1400
1405
  constructor(auditSlug, pluginSlug) {
@@ -1555,21 +1560,48 @@ var verboseUtils = (verbose = false) => ({
1555
1560
  exec: getExecVerbose(verbose)
1556
1561
  });
1557
1562
 
1558
- // packages/utils/src/lib/logging.ts
1559
- import chalk4 from "chalk";
1560
- function link2(text) {
1561
- return chalk4.underline(chalk4.blueBright(text));
1562
- }
1563
-
1564
1563
  // packages/core/package.json
1565
1564
  var name = "@code-pushup/core";
1566
- var version = "0.18.1";
1565
+ var version = "0.20.0";
1567
1566
 
1568
1567
  // packages/core/src/lib/implementation/execute-plugin.ts
1569
1568
  import chalk5 from "chalk";
1570
1569
 
1570
+ // packages/core/src/lib/normalize.ts
1571
+ function normalizePersistConfig(cfg) {
1572
+ return {
1573
+ outputDir: PERSIST_OUTPUT_DIR,
1574
+ filename: PERSIST_FILENAME,
1575
+ format: PERSIST_FORMAT,
1576
+ ...cfg
1577
+ };
1578
+ }
1579
+ async function normalizeAuditOutputs(audits) {
1580
+ const gitRoot = await getGitRoot();
1581
+ return audits.map((audit) => {
1582
+ if (audit.details?.issues == null || audit.details.issues.every((issue) => issue.source == null)) {
1583
+ return audit;
1584
+ }
1585
+ return {
1586
+ ...audit,
1587
+ details: {
1588
+ ...audit.details,
1589
+ issues: audit.details.issues.map(
1590
+ (issue) => issue.source == null ? issue : {
1591
+ ...issue,
1592
+ source: {
1593
+ ...issue.source,
1594
+ file: formatGitPath(issue.source.file, gitRoot)
1595
+ }
1596
+ }
1597
+ )
1598
+ }
1599
+ };
1600
+ });
1601
+ }
1602
+
1571
1603
  // packages/core/src/lib/implementation/runner.ts
1572
- import { join as join2 } from "node:path";
1604
+ import { join as join3 } from "node:path";
1573
1605
  async function executeRunnerConfig(cfg, onProgress) {
1574
1606
  const { args, command, outputFile, outputTransform } = cfg;
1575
1607
  const { duration, date } = await executeProcess({
@@ -1577,7 +1609,7 @@ async function executeRunnerConfig(cfg, onProgress) {
1577
1609
  args,
1578
1610
  observer: { onStdout: onProgress }
1579
1611
  });
1580
- const outputs = await readJsonFile(join2(process.cwd(), outputFile));
1612
+ const outputs = await readJsonFile(join3(process.cwd(), outputFile));
1581
1613
  const audits = outputTransform ? await outputTransform(outputs) : outputs;
1582
1614
  return {
1583
1615
  duration,
@@ -1615,7 +1647,8 @@ async function executePlugin(pluginConfig, onProgress) {
1615
1647
  const { audits: unvalidatedAuditOutputs, ...executionMeta } = runnerResult;
1616
1648
  const auditOutputs = auditOutputsSchema.parse(unvalidatedAuditOutputs);
1617
1649
  auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits);
1618
- const auditReports = auditOutputs.map(
1650
+ const normalizedAuditOutputs = await normalizeAuditOutputs(auditOutputs);
1651
+ const auditReports = normalizedAuditOutputs.map(
1619
1652
  (auditOutput) => ({
1620
1653
  ...auditOutput,
1621
1654
  ...pluginConfigAudits.find(
@@ -1693,7 +1726,7 @@ async function collect(options2) {
1693
1726
 
1694
1727
  // packages/core/src/lib/implementation/persist.ts
1695
1728
  import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
1696
- import { join as join3 } from "node:path";
1729
+ import { join as join4 } from "node:path";
1697
1730
  var PersistDirError = class extends Error {
1698
1731
  constructor(outputDir) {
1699
1732
  super(`outPath: ${outputDir} is no directory.`);
@@ -1737,7 +1770,7 @@ async function persistReport(report, options2) {
1737
1770
  return Promise.allSettled(
1738
1771
  results.map(
1739
1772
  (result) => persistResult(
1740
- join3(outputDir, `${filename}.${result.format}`),
1773
+ join4(outputDir, `${filename}.${result.format}`),
1741
1774
  result.content
1742
1775
  )
1743
1776
  )
@@ -1753,14 +1786,6 @@ function logPersistedResults(persistResults) {
1753
1786
  logMultipleFileResults(persistResults, "Generated reports");
1754
1787
  }
1755
1788
 
1756
- // packages/core/src/lib/normalize.ts
1757
- var normalizePersistConfig = (cfg) => ({
1758
- outputDir: PERSIST_OUTPUT_DIR,
1759
- filename: PERSIST_FILENAME,
1760
- format: PERSIST_FORMAT,
1761
- ...cfg
1762
- });
1763
-
1764
1789
  // packages/core/src/lib/collect-and-persist.ts
1765
1790
  async function collectAndPersistReports(options2) {
1766
1791
  const { exec } = verboseUtils(options2.verbose);
@@ -1776,7 +1801,7 @@ async function collectAndPersistReports(options2) {
1776
1801
  }
1777
1802
 
1778
1803
  // packages/core/src/lib/implementation/read-rc-file.ts
1779
- import { join as join4 } from "node:path";
1804
+ import { join as join5 } from "node:path";
1780
1805
  var ConfigPathError = class extends Error {
1781
1806
  constructor(configPath) {
1782
1807
  super(`Provided path '${configPath}' is not valid.`);
@@ -1809,7 +1834,7 @@ async function autoloadRc() {
1809
1834
  )}) present in ${process.cwd()}`
1810
1835
  );
1811
1836
  }
1812
- return readRcByPath(join4(process.cwd(), `${CONFIG_FILE_NAME}.${ext}`));
1837
+ return readRcByPath(join5(process.cwd(), `${CONFIG_FILE_NAME}.${ext}`));
1813
1838
  }
1814
1839
 
1815
1840
  // packages/core/src/lib/upload.ts
@@ -1961,7 +1986,7 @@ function ui() {
1961
1986
  function renderConfigureCategoriesHint() {
1962
1987
  ui().logger.info(
1963
1988
  chalk6.gray(
1964
- `\u{1F4A1} Configure categories to see the scores in an overview table. See: ${link2(
1989
+ `\u{1F4A1} Configure categories to see the scores in an overview table. See: ${link(
1965
1990
  "https://github.com/code-pushup/cli/blob/main/packages/cli/README.md"
1966
1991
  )}`
1967
1992
  )
@@ -1970,7 +1995,7 @@ function renderConfigureCategoriesHint() {
1970
1995
  function uploadSuccessfulLog(options2, commit) {
1971
1996
  ui().logger.success("Upload successful!");
1972
1997
  ui().logger.success(
1973
- link2(
1998
+ link(
1974
1999
  // @TODO extend config to maintain baseUrl under upload
1975
2000
  portalCommitDashboardLink(
1976
2001
  { ...options2, baseUrl: "<YOUR_PORTAL_URL>" },
@@ -1988,15 +2013,15 @@ function renderIntegratePortalHint() {
1988
2013
  "npx code-pushup upload"
1989
2014
  )}`
1990
2015
  ).add(
1991
- ` ${link2(
2016
+ ` ${link(
1992
2017
  "https://github.com/code-pushup/cli/tree/main/packages/cli#upload-command"
1993
2018
  )}`
1994
2019
  ).add(
1995
- `${chalk6.gray("\u276F")} ${chalk6.gray("Portal Integration")} - ${link2(
2020
+ `${chalk6.gray("\u276F")} ${chalk6.gray("Portal Integration")} - ${link(
1996
2021
  "https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#portal-integration"
1997
2022
  )}`
1998
2023
  ).add(
1999
- `${chalk6.gray("\u276F")} ${chalk6.gray("Upload Command")} - ${link2(
2024
+ `${chalk6.gray("\u276F")} ${chalk6.gray("Upload Command")} - ${link(
2000
2025
  "https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#portal-integration"
2001
2026
  )}`
2002
2027
  ).render();
@@ -2111,7 +2136,7 @@ function renderUploadAutorunHint() {
2111
2136
  "Run upload to upload the created report to the server"
2112
2137
  )}`
2113
2138
  ).add(
2114
- ` ${link2(
2139
+ ` ${link(
2115
2140
  "https://github.com/code-pushup/cli/tree/main/packages/cli#upload-command"
2116
2141
  )}`
2117
2142
  ).add(
@@ -2119,7 +2144,7 @@ function renderUploadAutorunHint() {
2119
2144
  "Run collect & upload"
2120
2145
  )}`
2121
2146
  ).add(
2122
- ` ${link2(
2147
+ ` ${link(
2123
2148
  "https://github.com/code-pushup/cli/tree/main/packages/cli#autorun-command"
2124
2149
  )}`
2125
2150
  ).render();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/cli",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "code-pushup": "index.js"
@@ -12,44 +12,5 @@
12
12
  "chalk": "^5.3.0",
13
13
  "@code-pushup/utils": "*",
14
14
  "@poppinss/cliui": "^6.3.0"
15
- },
16
- "homepage": "https://github.com/code-pushup/cli#readme",
17
- "bugs": {
18
- "url": "https://github.com/code-pushup/cli/issues"
19
- },
20
- "repository": {
21
- "type": "git",
22
- "url": "https://github.com/code-pushup/cli.git",
23
- "directory": "packages/cli"
24
- },
25
- "contributors": [
26
- {
27
- "name": "Igor Katsuba",
28
- "email": "igor@katsuba.dev",
29
- "url": "https://katsuba.dev"
30
- },
31
- {
32
- "name": "Kateřina Pilátová",
33
- "email": "katerina.pilatova@flowup.cz",
34
- "url": "https://github.com/Tlacenka"
35
- },
36
- {
37
- "name": "Matěj Chalk",
38
- "email": "matej.chalk@flowup.cz",
39
- "url": "https://github.com/matejchalk"
40
- },
41
- {
42
- "name": "Michael Hladky",
43
- "email": "michael.hladky@push-based.io",
44
- "url": "https://push-based.io"
45
- },
46
- {
47
- "name": "Michael Seredenko",
48
- "email": "misha.seredenko@push-based.io",
49
- "url": "https://github.com/MishaSeredenkoPushBased"
50
- }
51
- ],
52
- "type": "module",
53
- "main": "./index.js",
54
- "types": "./src/index.d.ts"
55
- }
15
+ }
16
+ }