@code-pushup/core 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.
package/index.js CHANGED
@@ -75,25 +75,15 @@ function executionMetaSchema(options = {
75
75
  duration: z.number({ description: options.descriptionDuration })
76
76
  });
77
77
  }
78
- function slugSchema(description = "Unique ID (human-readable, URL-safe)") {
79
- return z.string({ description }).regex(slugRegex, {
80
- message: "The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug"
81
- }).max(MAX_SLUG_LENGTH, {
82
- message: `slug can be max ${MAX_SLUG_LENGTH} characters long`
83
- });
84
- }
85
- function descriptionSchema(description = "Description (markdown)") {
86
- return z.string({ description }).max(MAX_DESCRIPTION_LENGTH).optional();
87
- }
88
- function docsUrlSchema(description = "Documentation site") {
89
- return urlSchema(description).optional().or(z.string().max(0));
90
- }
91
- function urlSchema(description) {
92
- return z.string({ description }).url();
93
- }
94
- function titleSchema(description = "Descriptive name") {
95
- return z.string({ description }).max(MAX_TITLE_LENGTH);
96
- }
78
+ var slugSchema = z.string({ description: "Unique ID (human-readable, URL-safe)" }).regex(slugRegex, {
79
+ message: "The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug"
80
+ }).max(MAX_SLUG_LENGTH, {
81
+ message: `slug can be max ${MAX_SLUG_LENGTH} characters long`
82
+ });
83
+ var descriptionSchema = z.string({ description: "Description (markdown)" }).max(MAX_DESCRIPTION_LENGTH).optional();
84
+ var urlSchema = z.string().url();
85
+ var docsUrlSchema = urlSchema.optional().or(z.literal("")).describe("Documentation site");
86
+ var titleSchema = z.string({ description: "Descriptive name" }).max(MAX_TITLE_LENGTH);
97
87
  function metaSchema(options) {
98
88
  const {
99
89
  descriptionDescription,
@@ -103,24 +93,19 @@ function metaSchema(options) {
103
93
  } = options ?? {};
104
94
  return z.object(
105
95
  {
106
- title: titleSchema(titleDescription),
107
- description: descriptionSchema(descriptionDescription),
108
- docsUrl: docsUrlSchema(docsUrlDescription)
96
+ title: titleDescription ? titleSchema.describe(titleDescription) : titleSchema,
97
+ description: descriptionDescription ? descriptionSchema.describe(descriptionDescription) : descriptionSchema,
98
+ docsUrl: docsUrlDescription ? docsUrlSchema.describe(docsUrlDescription) : docsUrlSchema
109
99
  },
110
100
  { description }
111
101
  );
112
102
  }
113
- function filePathSchema(description) {
114
- return z.string({ description }).trim().min(1, { message: "path is invalid" });
115
- }
116
- function fileNameSchema(description) {
117
- return z.string({ description }).trim().regex(filenameRegex, {
118
- message: `The filename has to be valid`
119
- }).min(1, { message: "file name is invalid" });
120
- }
121
- function positiveIntSchema(description) {
122
- return z.number({ description }).int().nonnegative();
123
- }
103
+ var filePathSchema = z.string().trim().min(1, { message: "path is invalid" });
104
+ var fileNameSchema = z.string().trim().regex(filenameRegex, {
105
+ message: `The filename has to be valid`
106
+ }).min(1, { message: "file name is invalid" });
107
+ var positiveIntSchema = z.number().int().positive();
108
+ var nonnegativeIntSchema = z.number().int().nonnegative();
124
109
  function packageVersionSchema(options) {
125
110
  const { versionDescription = "NPM version of the package", required } = options ?? {};
126
111
  const packageSchema = z.string({ description: "NPM package name" });
@@ -133,14 +118,14 @@ function packageVersionSchema(options) {
133
118
  { description: "NPM package name and version of a published package" }
134
119
  );
135
120
  }
136
- function weightSchema(description = "Coefficient for the given score (use weight 0 if only for display)") {
137
- return positiveIntSchema(description);
138
- }
121
+ var weightSchema = nonnegativeIntSchema.describe(
122
+ "Coefficient for the given score (use weight 0 if only for display)"
123
+ );
139
124
  function weightedRefSchema(description, slugDescription) {
140
125
  return z.object(
141
126
  {
142
- slug: slugSchema(slugDescription),
143
- weight: weightSchema("Weight used to calculate score")
127
+ slug: slugSchema.describe(slugDescription),
128
+ weight: weightSchema.describe("Weight used to calculate score")
144
129
  },
145
130
  { description }
146
131
  );
@@ -148,14 +133,14 @@ function weightedRefSchema(description, slugDescription) {
148
133
  function scorableSchema(description, refSchema, duplicateCheckFn, duplicateMessageFn) {
149
134
  return z.object(
150
135
  {
151
- slug: slugSchema('Human-readable unique ID, e.g. "performance"'),
136
+ slug: slugSchema.describe('Human-readable unique ID, e.g. "performance"'),
152
137
  refs: z.array(refSchema).min(1).refine(
153
138
  (refs) => !duplicateCheckFn(refs),
154
139
  (refs) => ({
155
140
  message: duplicateMessageFn(refs)
156
141
  })
157
- ).refine(hasWeightedRefsInCategories, () => ({
158
- message: `In a category there has to be at least one ref with weight > 0`
142
+ ).refine(hasNonZeroWeightedRef, () => ({
143
+ message: "In a category there has to be at least one ref with weight > 0"
159
144
  }))
160
145
  },
161
146
  { description }
@@ -164,13 +149,13 @@ function scorableSchema(description, refSchema, duplicateCheckFn, duplicateMessa
164
149
  var materialIconSchema = z.enum(MATERIAL_ICONS, {
165
150
  description: "Icon from VSCode Material Icons extension"
166
151
  });
167
- function hasWeightedRefsInCategories(categoryRefs) {
168
- return categoryRefs.reduce((acc, { weight }) => weight + acc, 0) !== 0;
152
+ function hasNonZeroWeightedRef(refs) {
153
+ return refs.reduce((acc, { weight }) => weight + acc, 0) !== 0;
169
154
  }
170
155
 
171
156
  // packages/models/src/lib/audit.ts
172
157
  var auditSchema = z2.object({
173
- slug: slugSchema("ID (unique within plugin)")
158
+ slug: slugSchema.describe("ID (unique within plugin)")
174
159
  }).merge(
175
160
  metaSchema({
176
161
  titleDescription: "Descriptive name",
@@ -197,17 +182,20 @@ function getDuplicateSlugsInAudits(audits) {
197
182
  return hasDuplicateStrings(audits.map(({ slug }) => slug));
198
183
  }
199
184
 
200
- // packages/models/src/lib/audit-issue.ts
185
+ // packages/models/src/lib/audit-output.ts
186
+ import { z as z4 } from "zod";
187
+
188
+ // packages/models/src/lib/issue.ts
201
189
  import { z as z3 } from "zod";
202
190
  var sourceFileLocationSchema = z3.object(
203
191
  {
204
- file: filePathSchema("Relative path to source file in Git repo"),
192
+ file: filePathSchema.describe("Relative path to source file in Git repo"),
205
193
  position: z3.object(
206
194
  {
207
- startLine: positiveIntSchema("Start line"),
208
- startColumn: positiveIntSchema("Start column").optional(),
209
- endLine: positiveIntSchema("End line").optional(),
210
- endColumn: positiveIntSchema("End column").optional()
195
+ startLine: positiveIntSchema.describe("Start line"),
196
+ startColumn: positiveIntSchema.describe("Start column").optional(),
197
+ endLine: positiveIntSchema.describe("End line").optional(),
198
+ endColumn: positiveIntSchema.describe("End column").optional()
211
199
  },
212
200
  { description: "Location in file" }
213
201
  ).optional()
@@ -227,21 +215,21 @@ var issueSchema = z3.object(
227
215
  );
228
216
 
229
217
  // packages/models/src/lib/audit-output.ts
230
- import { z as z4 } from "zod";
218
+ var auditDetailsSchema = z4.object(
219
+ {
220
+ issues: z4.array(issueSchema, { description: "List of findings" })
221
+ },
222
+ { description: "Detailed information" }
223
+ );
231
224
  var auditOutputSchema = z4.object(
232
225
  {
233
- slug: slugSchema("Reference to audit"),
226
+ slug: slugSchema.describe("Reference to audit"),
234
227
  displayValue: z4.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional(),
235
- value: positiveIntSchema("Raw numeric value"),
228
+ value: nonnegativeIntSchema.describe("Raw numeric value"),
236
229
  score: z4.number({
237
230
  description: "Value between 0 and 1"
238
231
  }).min(0).max(1),
239
- details: z4.object(
240
- {
241
- issues: z4.array(issueSchema, { description: "List of findings" })
242
- },
243
- { description: "Detailed information" }
244
- ).optional()
232
+ details: auditDetailsSchema.optional()
245
233
  },
246
234
  { description: "Audit information" }
247
235
  );
@@ -271,7 +259,7 @@ var categoryRefSchema = weightedRefSchema(
271
259
  type: z5.enum(["audit", "group"], {
272
260
  description: "Discriminant for reference kind, affects where `slug` is looked up"
273
261
  }),
274
- plugin: slugSchema(
262
+ plugin: slugSchema.describe(
275
263
  "Plugin slug (plugin should contain referenced audit or group)"
276
264
  )
277
265
  })
@@ -331,10 +319,8 @@ import { z as z11 } from "zod";
331
319
  import { z as z6 } from "zod";
332
320
  var formatSchema = z6.enum(["json", "md"]);
333
321
  var persistConfigSchema = z6.object({
334
- outputDir: filePathSchema("Artifacts folder").optional(),
335
- filename: fileNameSchema(
336
- "Artifacts file name (without extension)"
337
- ).optional(),
322
+ outputDir: filePathSchema.describe("Artifacts folder").optional(),
323
+ filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
338
324
  format: z6.array(formatSchema).optional()
339
325
  });
340
326
 
@@ -395,7 +381,7 @@ var runnerConfigSchema = z8.object(
395
381
  description: "Shell command to execute"
396
382
  }),
397
383
  args: z8.array(z8.string({ description: "Command arguments" })).optional(),
398
- outputFile: filePathSchema("Output path"),
384
+ outputFile: filePathSchema.describe("Output path"),
399
385
  outputTransform: outputTransformSchema.optional()
400
386
  },
401
387
  {
@@ -415,7 +401,7 @@ var pluginMetaSchema = packageVersionSchema().merge(
415
401
  })
416
402
  ).merge(
417
403
  z9.object({
418
- slug: slugSchema("Unique plugin slug within core config"),
404
+ slug: slugSchema.describe("Unique plugin slug within core config"),
419
405
  icon: materialIconSchema
420
406
  })
421
407
  );
@@ -448,12 +434,14 @@ function getMissingRefsFromGroups(pluginCfg) {
448
434
  // packages/models/src/lib/upload-config.ts
449
435
  import { z as z10 } from "zod";
450
436
  var uploadConfigSchema = z10.object({
451
- server: urlSchema("URL of deployed portal API"),
437
+ server: urlSchema.describe("URL of deployed portal API"),
452
438
  apiKey: z10.string({
453
439
  description: "API key with write access to portal (use `process.env` for security)"
454
440
  }),
455
- organization: slugSchema("Organization slug from Code PushUp portal"),
456
- project: slugSchema("Project slug from Code PushUp portal"),
441
+ organization: slugSchema.describe(
442
+ "Organization slug from Code PushUp portal"
443
+ ),
444
+ project: slugSchema.describe("Project slug from Code PushUp portal"),
457
445
  timeout: z10.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
458
446
  });
459
447
 
@@ -956,16 +944,32 @@ function executeProcess(cfg) {
956
944
  });
957
945
  }
958
946
 
947
+ // packages/utils/src/lib/transform.ts
948
+ function deepClone(obj) {
949
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
950
+ }
951
+ function toUnixPath(path) {
952
+ return path.replace(/\\/g, "/");
953
+ }
954
+
959
955
  // packages/utils/src/lib/git.ts
956
+ import { isAbsolute, join as join2, relative } from "node:path";
960
957
  import { simpleGit } from "simple-git";
961
- var git = simpleGit();
962
- async function getLatestCommit() {
958
+ async function getLatestCommit(git = simpleGit()) {
963
959
  const log = await git.log({
964
960
  maxCount: 1,
965
961
  format: { hash: "%H", message: "%s", author: "%an", date: "%ad" }
966
962
  });
967
963
  return log.latest;
968
964
  }
965
+ function getGitRoot(git = simpleGit()) {
966
+ return git.revparse("--show-toplevel");
967
+ }
968
+ function formatGitPath(path, gitRoot) {
969
+ const absolutePath = isAbsolute(path) ? path : join2(process.cwd(), path);
970
+ const relativePath = relative(gitRoot, absolutePath);
971
+ return toUnixPath(relativePath);
972
+ }
969
973
  function validateCommitData(commitData, options = {}) {
970
974
  const { throwError = false } = options;
971
975
  if (!commitData) {
@@ -988,18 +992,21 @@ function groupByStatus(results) {
988
992
  );
989
993
  }
990
994
 
991
- // packages/utils/src/lib/progress.ts
995
+ // packages/utils/src/lib/logging.ts
992
996
  import chalk2 from "chalk";
997
+
998
+ // packages/utils/src/lib/progress.ts
999
+ import chalk3 from "chalk";
993
1000
  import { MultiProgressBars } from "multi-progress-bars";
994
1001
  var barStyles = {
995
- active: (s) => chalk2.green(s),
996
- done: (s) => chalk2.gray(s),
997
- idle: (s) => chalk2.gray(s)
1002
+ active: (s) => chalk3.green(s),
1003
+ done: (s) => chalk3.gray(s),
1004
+ idle: (s) => chalk3.gray(s)
998
1005
  };
999
1006
  var messageStyles = {
1000
- active: (s) => chalk2.black(s),
1001
- done: (s) => chalk2.green(chalk2.bold(s)),
1002
- idle: (s) => chalk2.gray(s)
1007
+ active: (s) => chalk3.black(s),
1008
+ done: (s) => chalk3.green(chalk3.bold(s)),
1009
+ idle: (s) => chalk3.gray(s)
1003
1010
  };
1004
1011
  var mpb;
1005
1012
  function getSingletonProgressBars(options) {
@@ -1298,7 +1305,7 @@ function getAuditResult(audit, isHtml = false) {
1298
1305
 
1299
1306
  // packages/utils/src/lib/reports/generate-stdout-summary.ts
1300
1307
  import cliui from "@isaacs/cliui";
1301
- import chalk3 from "chalk";
1308
+ import chalk4 from "chalk";
1302
1309
  import CliTable3 from "cli-table3";
1303
1310
  function addLine(line = "") {
1304
1311
  return line + NEW_LINE;
@@ -1309,7 +1316,7 @@ function generateStdoutSummary(report) {
1309
1316
  }
1310
1317
  function reportToHeaderSection2(report) {
1311
1318
  const { packageName, version: version2 } = report;
1312
- return `${chalk3.bold(reportHeadlineText)} - ${packageName}@${version2}`;
1319
+ return `${chalk4.bold(reportHeadlineText)} - ${packageName}@${version2}`;
1313
1320
  }
1314
1321
  function reportToDetailSection(report) {
1315
1322
  const { plugins } = report;
@@ -1329,13 +1336,13 @@ function reportToDetailSection(report) {
1329
1336
  padding: [0, 3, 0, 0]
1330
1337
  },
1331
1338
  {
1332
- text: chalk3.cyanBright(audit.displayValue || `${audit.value}`),
1339
+ text: chalk4.cyanBright(audit.displayValue || `${audit.value}`),
1333
1340
  width: 10,
1334
1341
  padding: [0, 0, 0, 0]
1335
1342
  }
1336
1343
  );
1337
1344
  });
1338
- return acc + addLine() + addLine(chalk3.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui.toString()) + addLine();
1345
+ return acc + addLine() + addLine(chalk4.magentaBright.bold(`${title} audits`)) + addLine() + addLine(ui.toString()) + addLine();
1339
1346
  }, "");
1340
1347
  }
1341
1348
  function reportToOverviewSection2({
@@ -1358,11 +1365,11 @@ function reportToOverviewSection2({
1358
1365
  countCategoryAudits(refs, plugins)
1359
1366
  ])
1360
1367
  );
1361
- return addLine(chalk3.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1368
+ return addLine(chalk4.magentaBright.bold("Categories")) + addLine() + addLine(table.toString());
1362
1369
  }
1363
1370
  function withColor({ score, text }) {
1364
1371
  const formattedScore = text ?? formatReportScore(score);
1365
- const style2 = text ? chalk3 : chalk3.bold;
1372
+ const style2 = text ? chalk4 : chalk4.bold;
1366
1373
  if (score >= SCORE_COLOR_RANGE.GREEN_MIN) {
1367
1374
  return style2.green(formattedScore);
1368
1375
  }
@@ -1372,11 +1379,6 @@ function withColor({ score, text }) {
1372
1379
  return style2.red(formattedScore);
1373
1380
  }
1374
1381
 
1375
- // packages/utils/src/lib/transform.ts
1376
- function deepClone(obj) {
1377
- return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1378
- }
1379
-
1380
1382
  // packages/utils/src/lib/reports/scoring.ts
1381
1383
  var GroupRefInvalidError = class extends Error {
1382
1384
  constructor(auditSlug, pluginSlug) {
@@ -1537,18 +1539,48 @@ var verboseUtils = (verbose = false) => ({
1537
1539
  exec: getExecVerbose(verbose)
1538
1540
  });
1539
1541
 
1540
- // packages/utils/src/lib/logging.ts
1541
- import chalk4 from "chalk";
1542
-
1543
1542
  // packages/core/package.json
1544
1543
  var name = "@code-pushup/core";
1545
- var version = "0.18.1";
1544
+ var version = "0.20.0";
1546
1545
 
1547
1546
  // packages/core/src/lib/implementation/execute-plugin.ts
1548
1547
  import chalk5 from "chalk";
1549
1548
 
1549
+ // packages/core/src/lib/normalize.ts
1550
+ function normalizePersistConfig(cfg) {
1551
+ return {
1552
+ outputDir: PERSIST_OUTPUT_DIR,
1553
+ filename: PERSIST_FILENAME,
1554
+ format: PERSIST_FORMAT,
1555
+ ...cfg
1556
+ };
1557
+ }
1558
+ async function normalizeAuditOutputs(audits) {
1559
+ const gitRoot = await getGitRoot();
1560
+ return audits.map((audit) => {
1561
+ if (audit.details?.issues == null || audit.details.issues.every((issue) => issue.source == null)) {
1562
+ return audit;
1563
+ }
1564
+ return {
1565
+ ...audit,
1566
+ details: {
1567
+ ...audit.details,
1568
+ issues: audit.details.issues.map(
1569
+ (issue) => issue.source == null ? issue : {
1570
+ ...issue,
1571
+ source: {
1572
+ ...issue.source,
1573
+ file: formatGitPath(issue.source.file, gitRoot)
1574
+ }
1575
+ }
1576
+ )
1577
+ }
1578
+ };
1579
+ });
1580
+ }
1581
+
1550
1582
  // packages/core/src/lib/implementation/runner.ts
1551
- import { join as join2 } from "node:path";
1583
+ import { join as join3 } from "node:path";
1552
1584
  async function executeRunnerConfig(cfg, onProgress) {
1553
1585
  const { args, command, outputFile, outputTransform } = cfg;
1554
1586
  const { duration, date } = await executeProcess({
@@ -1556,7 +1588,7 @@ async function executeRunnerConfig(cfg, onProgress) {
1556
1588
  args,
1557
1589
  observer: { onStdout: onProgress }
1558
1590
  });
1559
- const outputs = await readJsonFile(join2(process.cwd(), outputFile));
1591
+ const outputs = await readJsonFile(join3(process.cwd(), outputFile));
1560
1592
  const audits = outputTransform ? await outputTransform(outputs) : outputs;
1561
1593
  return {
1562
1594
  duration,
@@ -1594,7 +1626,8 @@ async function executePlugin(pluginConfig, onProgress) {
1594
1626
  const { audits: unvalidatedAuditOutputs, ...executionMeta } = runnerResult;
1595
1627
  const auditOutputs = auditOutputsSchema.parse(unvalidatedAuditOutputs);
1596
1628
  auditOutputsCorrelateWithPluginOutput(auditOutputs, pluginConfigAudits);
1597
- const auditReports = auditOutputs.map(
1629
+ const normalizedAuditOutputs = await normalizeAuditOutputs(auditOutputs);
1630
+ const auditReports = normalizedAuditOutputs.map(
1598
1631
  (auditOutput) => ({
1599
1632
  ...auditOutput,
1600
1633
  ...pluginConfigAudits.find(
@@ -1672,7 +1705,7 @@ async function collect(options) {
1672
1705
 
1673
1706
  // packages/core/src/lib/implementation/persist.ts
1674
1707
  import { mkdir as mkdir2, stat as stat2, writeFile } from "node:fs/promises";
1675
- import { join as join3 } from "node:path";
1708
+ import { join as join4 } from "node:path";
1676
1709
  var PersistDirError = class extends Error {
1677
1710
  constructor(outputDir) {
1678
1711
  super(`outPath: ${outputDir} is no directory.`);
@@ -1716,7 +1749,7 @@ async function persistReport(report, options) {
1716
1749
  return Promise.allSettled(
1717
1750
  results.map(
1718
1751
  (result) => persistResult(
1719
- join3(outputDir, `${filename}.${result.format}`),
1752
+ join4(outputDir, `${filename}.${result.format}`),
1720
1753
  result.content
1721
1754
  )
1722
1755
  )
@@ -1732,14 +1765,6 @@ function logPersistedResults(persistResults) {
1732
1765
  logMultipleFileResults(persistResults, "Generated reports");
1733
1766
  }
1734
1767
 
1735
- // packages/core/src/lib/normalize.ts
1736
- var normalizePersistConfig = (cfg) => ({
1737
- outputDir: PERSIST_OUTPUT_DIR,
1738
- filename: PERSIST_FILENAME,
1739
- format: PERSIST_FORMAT,
1740
- ...cfg
1741
- });
1742
-
1743
1768
  // packages/core/src/lib/collect-and-persist.ts
1744
1769
  async function collectAndPersistReports(options) {
1745
1770
  const { exec } = verboseUtils(options.verbose);
@@ -1755,7 +1780,7 @@ async function collectAndPersistReports(options) {
1755
1780
  }
1756
1781
 
1757
1782
  // packages/core/src/lib/implementation/read-rc-file.ts
1758
- import { join as join4 } from "node:path";
1783
+ import { join as join5 } from "node:path";
1759
1784
  var ConfigPathError = class extends Error {
1760
1785
  constructor(configPath) {
1761
1786
  super(`Provided path '${configPath}' is not valid.`);
@@ -1788,7 +1813,7 @@ async function autoloadRc() {
1788
1813
  )}) present in ${process.cwd()}`
1789
1814
  );
1790
1815
  }
1791
- return readRcByPath(join4(process.cwd(), `${CONFIG_FILE_NAME}.${ext}`));
1816
+ return readRcByPath(join5(process.cwd(), `${CONFIG_FILE_NAME}.${ext}`));
1792
1817
  }
1793
1818
 
1794
1819
  // packages/core/src/lib/upload.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-pushup/core",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "license": "MIT",
5
5
  "dependencies": {
6
6
  "@code-pushup/models": "*",
@@ -1,2 +1,3 @@
1
- import { PersistConfig } from '@code-pushup/models';
2
- export declare const normalizePersistConfig: (cfg?: Partial<PersistConfig>) => Required<PersistConfig>;
1
+ import { type AuditOutputs, PersistConfig } from '@code-pushup/models';
2
+ export declare function normalizePersistConfig(cfg?: Partial<PersistConfig>): Required<PersistConfig>;
3
+ export declare function normalizeAuditOutputs(audits: AuditOutputs): Promise<AuditOutputs>;