@code-pushup/js-packages-plugin 0.39.0 → 0.42.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/bin.js CHANGED
@@ -2,8 +2,299 @@
2
2
  import { writeFile } from "node:fs/promises";
3
3
  import { dirname } from "node:path";
4
4
 
5
- // packages/models/src/lib/audit.ts
6
- import { z as z2 } from "zod";
5
+ // packages/utils/src/lib/text-formats/constants.ts
6
+ var NEW_LINE = "\n";
7
+ var TAB = " ";
8
+
9
+ // packages/utils/src/lib/text-formats/html/details.ts
10
+ function details(title, content, cfg = { open: false }) {
11
+ return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
12
+ NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
13
+ // ⚠️ The blank line ensure Markdown in content is rendered correctly.
14
+ NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
15
+ NEW_LINE}`;
16
+ }
17
+
18
+ // packages/utils/src/lib/text-formats/html/font-style.ts
19
+ var boldElement = "b";
20
+ function bold(text) {
21
+ return `<${boldElement}>${text}</${boldElement}>`;
22
+ }
23
+ var italicElement = "i";
24
+ function italic(text) {
25
+ return `<${italicElement}>${text}</${italicElement}>`;
26
+ }
27
+ var codeElement = "code";
28
+ function code(text) {
29
+ return `<${codeElement}>${text}</${codeElement}>`;
30
+ }
31
+
32
+ // packages/utils/src/lib/text-formats/html/link.ts
33
+ function link(href, text) {
34
+ return `<a href="${href}">${text || href}"</a>`;
35
+ }
36
+
37
+ // packages/utils/src/lib/transform.ts
38
+ import { platform } from "node:os";
39
+ function objectToKeys(obj) {
40
+ return Object.keys(obj);
41
+ }
42
+ function objectToEntries(obj) {
43
+ return Object.entries(obj);
44
+ }
45
+ function objectFromEntries(entries) {
46
+ return Object.fromEntries(entries);
47
+ }
48
+ function toUnixNewlines(text) {
49
+ return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
50
+ }
51
+ function fromJsonLines(jsonLines) {
52
+ const unifiedNewLines = toUnixNewlines(jsonLines).trim();
53
+ return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
54
+ }
55
+ function capitalize(text) {
56
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
57
+ 1
58
+ )}`;
59
+ }
60
+ function apostrophize(text, upperCase) {
61
+ const lastCharMatch = text.match(/(\w)\W*$/);
62
+ const lastChar = lastCharMatch?.[1] ?? "";
63
+ return `${text}'${lastChar.toLocaleLowerCase() === "s" ? "" : upperCase ? "S" : "s"}`;
64
+ }
65
+
66
+ // packages/utils/src/lib/table.ts
67
+ function rowToStringArray({ rows, columns = [] }) {
68
+ if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
69
+ throw new TypeError(
70
+ "Column can`t be object when rows are primitive values"
71
+ );
72
+ }
73
+ return rows.map((row) => {
74
+ if (Array.isArray(row)) {
75
+ return row.map(String);
76
+ }
77
+ const objectRow = row;
78
+ if (columns.length === 0 || typeof columns.at(0) === "string") {
79
+ return Object.values(objectRow).map(String);
80
+ }
81
+ return columns.map(
82
+ ({ key }) => String(objectRow[key])
83
+ );
84
+ });
85
+ }
86
+ function columnsToStringArray({ rows, columns = [] }) {
87
+ const firstRow = rows.at(0);
88
+ const primitiveRows = Array.isArray(firstRow);
89
+ if (typeof columns.at(0) === "string" && !primitiveRows) {
90
+ throw new Error("invalid union type. Caught by model parsing.");
91
+ }
92
+ if (columns.length === 0) {
93
+ if (Array.isArray(firstRow)) {
94
+ return firstRow.map((_, idx) => String(idx));
95
+ }
96
+ return Object.keys(firstRow);
97
+ }
98
+ if (typeof columns.at(0) === "string") {
99
+ return columns.map(String);
100
+ }
101
+ const cols = columns;
102
+ return cols.map(({ label, key }) => label ?? capitalize(key));
103
+ }
104
+ function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
105
+ const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
106
+ if (typeof column === "string") {
107
+ return column;
108
+ } else if (typeof column === "object") {
109
+ return column.align ?? "center";
110
+ } else {
111
+ return "center";
112
+ }
113
+ }
114
+ function getColumnAlignmentForIndex(targetIdx, columns = []) {
115
+ const column = columns.at(targetIdx);
116
+ if (column == null) {
117
+ return "center";
118
+ } else if (typeof column === "string") {
119
+ return column;
120
+ } else if (typeof column === "object") {
121
+ return column.align ?? "center";
122
+ } else {
123
+ return "center";
124
+ }
125
+ }
126
+ function getColumnAlignments({
127
+ rows,
128
+ columns = []
129
+ }) {
130
+ if (rows.at(0) == null) {
131
+ throw new Error("first row can`t be undefined.");
132
+ }
133
+ if (Array.isArray(rows.at(0))) {
134
+ const firstPrimitiveRow = rows.at(0);
135
+ return Array.from({ length: firstPrimitiveRow.length }).map(
136
+ (_, idx) => getColumnAlignmentForIndex(idx, columns)
137
+ );
138
+ }
139
+ const firstObject = rows.at(0);
140
+ return Object.keys(firstObject).map(
141
+ (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
142
+ );
143
+ }
144
+
145
+ // packages/utils/src/lib/text-formats/html/table.ts
146
+ function wrap(elem, content) {
147
+ return `<${elem}>${content}</${elem}>${NEW_LINE}`;
148
+ }
149
+ function wrapRow(content) {
150
+ const elem = "tr";
151
+ return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
152
+ }
153
+ function table(tableData) {
154
+ if (tableData.rows.length === 0) {
155
+ throw new Error("Data can't be empty");
156
+ }
157
+ const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
158
+ const tableHeaderRow = wrapRow(tableHeaderCols);
159
+ const tableBody = rowToStringArray(tableData).map((arr) => {
160
+ const columns = arr.map((s) => wrap("td", s)).join("");
161
+ return wrapRow(columns);
162
+ }).join("");
163
+ return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
164
+ }
165
+
166
+ // packages/utils/src/lib/text-formats/md/font-style.ts
167
+ var boldWrap = "**";
168
+ function bold2(text) {
169
+ return `${boldWrap}${text}${boldWrap}`;
170
+ }
171
+ var italicWrap = "_";
172
+ function italic2(text) {
173
+ return `${italicWrap}${text}${italicWrap}`;
174
+ }
175
+ var strikeThroughWrap = "~";
176
+ function strikeThrough(text) {
177
+ return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
178
+ }
179
+ var codeWrap = "`";
180
+ function code2(text) {
181
+ return `${codeWrap}${text}${codeWrap}`;
182
+ }
183
+
184
+ // packages/utils/src/lib/text-formats/md/headline.ts
185
+ function headline(text, hierarchy = 1) {
186
+ return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
187
+ }
188
+ function h(text, hierarchy = 1) {
189
+ return headline(text, hierarchy);
190
+ }
191
+ function h1(text) {
192
+ return headline(text, 1);
193
+ }
194
+ function h2(text) {
195
+ return headline(text, 2);
196
+ }
197
+ function h3(text) {
198
+ return headline(text, 3);
199
+ }
200
+ function h4(text) {
201
+ return headline(text, 4);
202
+ }
203
+ function h5(text) {
204
+ return headline(text, 5);
205
+ }
206
+ function h6(text) {
207
+ return headline(text, 6);
208
+ }
209
+
210
+ // packages/utils/src/lib/text-formats/md/image.ts
211
+ function image(src, alt) {
212
+ return `![${alt}](${src})`;
213
+ }
214
+
215
+ // packages/utils/src/lib/text-formats/md/link.ts
216
+ function link2(href, text) {
217
+ return `[${text || href}](${href})`;
218
+ }
219
+
220
+ // packages/utils/src/lib/text-formats/md/list.ts
221
+ function li(text, order = "unordered") {
222
+ const style = order === "unordered" ? "-" : "- [ ]";
223
+ return `${style} ${text}`;
224
+ }
225
+ function indentation(text, level = 1) {
226
+ return `${TAB.repeat(level)}${text}`;
227
+ }
228
+
229
+ // packages/utils/src/lib/text-formats/md/paragraphs.ts
230
+ function paragraphs(...sections) {
231
+ return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
232
+ }
233
+
234
+ // packages/utils/src/lib/text-formats/md/section.ts
235
+ function section(...contents) {
236
+ return `${lines(...contents)}${NEW_LINE}`;
237
+ }
238
+ function lines(...contents) {
239
+ return `${contents.filter(Boolean).join(NEW_LINE)}`;
240
+ }
241
+
242
+ // packages/utils/src/lib/text-formats/md/table.ts
243
+ var alignString = /* @__PURE__ */ new Map([
244
+ ["left", ":--"],
245
+ ["center", ":--:"],
246
+ ["right", "--:"]
247
+ ]);
248
+ function tableRow(rows) {
249
+ return `|${rows.join("|")}|`;
250
+ }
251
+ function table2(data) {
252
+ if (data.rows.length === 0) {
253
+ throw new Error("Data can't be empty");
254
+ }
255
+ const alignmentRow = getColumnAlignments(data).map(
256
+ (s) => alignString.get(s) ?? String(alignString.get("center"))
257
+ );
258
+ return section(
259
+ `${lines(
260
+ tableRow(columnsToStringArray(data)),
261
+ tableRow(alignmentRow),
262
+ ...rowToStringArray(data).map(tableRow)
263
+ )}`
264
+ );
265
+ }
266
+
267
+ // packages/utils/src/lib/text-formats/index.ts
268
+ var md = {
269
+ bold: bold2,
270
+ italic: italic2,
271
+ strikeThrough,
272
+ code: code2,
273
+ link: link2,
274
+ image,
275
+ headline,
276
+ h,
277
+ h1,
278
+ h2,
279
+ h3,
280
+ h4,
281
+ h5,
282
+ h6,
283
+ indentation,
284
+ lines,
285
+ li,
286
+ section,
287
+ paragraphs,
288
+ table: table2
289
+ };
290
+ var html = {
291
+ bold,
292
+ italic,
293
+ code,
294
+ link,
295
+ details,
296
+ table
297
+ };
7
298
 
8
299
  // packages/models/src/lib/implementation/schemas.ts
9
300
  import { MATERIAL_ICONS } from "vscode-material-icons";
@@ -70,6 +361,7 @@ function missingRefsForCategoriesErrorMsg(categories, plugins) {
70
361
  }
71
362
 
72
363
  // packages/models/src/lib/implementation/schemas.ts
364
+ var primitiveValueSchema = z.union([z.string(), z.number()]);
73
365
  function executionMetaSchema(options = {
74
366
  descriptionDate: "Execution start date and time",
75
367
  descriptionDuration: "Execution duration in ms"
@@ -161,6 +453,7 @@ function hasNonZeroWeightedRef(refs) {
161
453
  }
162
454
 
163
455
  // packages/models/src/lib/audit.ts
456
+ import { z as z2 } from "zod";
164
457
  var auditSchema = z2.object({
165
458
  slug: slugSchema.describe("ID (unique within plugin)")
166
459
  }).merge(
@@ -190,7 +483,7 @@ function getDuplicateSlugsInAudits(audits) {
190
483
  }
191
484
 
192
485
  // packages/models/src/lib/audit-output.ts
193
- import { z as z4 } from "zod";
486
+ import { z as z5 } from "zod";
194
487
 
195
488
  // packages/models/src/lib/issue.ts
196
489
  import { z as z3 } from "zod";
@@ -221,16 +514,61 @@ var issueSchema = z3.object(
221
514
  { description: "Issue information" }
222
515
  );
223
516
 
517
+ // packages/models/src/lib/table.ts
518
+ import { z as z4 } from "zod";
519
+ var tableAlignmentSchema = z4.enum(["left", "center", "right"], {
520
+ description: "Cell alignment"
521
+ });
522
+ var tableColumnObjectSchema = z4.object({
523
+ key: z4.string(),
524
+ label: z4.string().optional(),
525
+ align: tableAlignmentSchema.optional()
526
+ });
527
+ var tableRowObjectSchema = z4.record(primitiveValueSchema, {
528
+ description: "Object row"
529
+ });
530
+ var tableRowPrimitiveSchema = z4.array(primitiveValueSchema, {
531
+ description: "Primitive row"
532
+ });
533
+ var tableSharedSchema = z4.object({
534
+ title: z4.string().optional().describe("Display title for table")
535
+ });
536
+ var tablePrimitiveSchema = tableSharedSchema.merge(
537
+ z4.object(
538
+ {
539
+ columns: z4.array(tableAlignmentSchema).optional(),
540
+ rows: z4.array(tableRowPrimitiveSchema)
541
+ },
542
+ { description: "Table with primitive rows and optional alignment columns" }
543
+ )
544
+ );
545
+ var tableObjectSchema = tableSharedSchema.merge(
546
+ z4.object(
547
+ {
548
+ columns: z4.union([
549
+ z4.array(tableAlignmentSchema),
550
+ z4.array(tableColumnObjectSchema)
551
+ ]).optional(),
552
+ rows: z4.array(tableRowObjectSchema)
553
+ },
554
+ {
555
+ description: "Table with object rows and optional alignment or object columns"
556
+ }
557
+ )
558
+ );
559
+ var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
560
+
224
561
  // packages/models/src/lib/audit-output.ts
225
562
  var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
226
- var auditDisplayValueSchema = z4.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
227
- var auditDetailsSchema = z4.object(
563
+ var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
564
+ var auditDetailsSchema = z5.object(
228
565
  {
229
- issues: z4.array(issueSchema, { description: "List of findings" })
566
+ issues: z5.array(issueSchema, { description: "List of findings" }).optional(),
567
+ table: tableSchema("Table of related findings").optional()
230
568
  },
231
569
  { description: "Detailed information" }
232
570
  );
233
- var auditOutputSchema = z4.object(
571
+ var auditOutputSchema = z5.object(
234
572
  {
235
573
  slug: slugSchema.describe("Reference to audit"),
236
574
  displayValue: auditDisplayValueSchema,
@@ -240,7 +578,7 @@ var auditOutputSchema = z4.object(
240
578
  },
241
579
  { description: "Audit information" }
242
580
  );
243
- var auditOutputsSchema = z4.array(auditOutputSchema, {
581
+ var auditOutputsSchema = z5.array(auditOutputSchema, {
244
582
  description: "List of JSON formatted audit output emitted by the runner process of a plugin"
245
583
  }).refine(
246
584
  (audits) => !getDuplicateSlugsInAudits2(audits),
@@ -257,13 +595,13 @@ function getDuplicateSlugsInAudits2(audits) {
257
595
  }
258
596
 
259
597
  // packages/models/src/lib/category-config.ts
260
- import { z as z5 } from "zod";
598
+ import { z as z6 } from "zod";
261
599
  var categoryRefSchema = weightedRefSchema(
262
600
  "Weighted references to audits and/or groups for the category",
263
601
  "Slug of an audit or group (depending on `type`)"
264
602
  ).merge(
265
- z5.object({
266
- type: z5.enum(["audit", "group"], {
603
+ z6.object({
604
+ type: z6.enum(["audit", "group"], {
267
605
  description: "Discriminant for reference kind, affects where `slug` is looked up"
268
606
  }),
269
607
  plugin: slugSchema.describe(
@@ -284,8 +622,8 @@ var categoryConfigSchema = scorableSchema(
284
622
  description: "Meta info for category"
285
623
  })
286
624
  ).merge(
287
- z5.object({
288
- isBinary: z5.boolean({
625
+ z6.object({
626
+ isBinary: z6.boolean({
289
627
  description: 'Is this a binary category (i.e. only a perfect score considered a "pass")?'
290
628
  }).optional()
291
629
  })
@@ -301,7 +639,7 @@ function getDuplicateRefsInCategoryMetrics(metrics) {
301
639
  metrics.map(({ slug, type, plugin }) => `${type} :: ${plugin} / ${slug}`)
302
640
  );
303
641
  }
304
- var categoriesSchema = z5.array(categoryConfigSchema, {
642
+ var categoriesSchema = z6.array(categoryConfigSchema, {
305
643
  description: "Categorization of individual audits"
306
644
  }).refine(
307
645
  (categoryCfg) => !getDuplicateSlugCategories(categoryCfg),
@@ -320,18 +658,18 @@ function getDuplicateSlugCategories(categories) {
320
658
  }
321
659
 
322
660
  // packages/models/src/lib/commit.ts
323
- import { z as z6 } from "zod";
324
- var commitSchema = z6.object(
661
+ import { z as z7 } from "zod";
662
+ var commitSchema = z7.object(
325
663
  {
326
- hash: z6.string({ description: "Commit SHA (full)" }).regex(
664
+ hash: z7.string({ description: "Commit SHA (full)" }).regex(
327
665
  /^[\da-f]{40}$/,
328
666
  "Commit SHA should be a 40-character hexadecimal string"
329
667
  ),
330
- message: z6.string({ description: "Commit message" }),
331
- date: z6.coerce.date({
668
+ message: z7.string({ description: "Commit message" }),
669
+ date: z7.coerce.date({
332
670
  description: "Date and time when commit was authored"
333
671
  }),
334
- author: z6.string({
672
+ author: z7.string({
335
673
  description: "Commit author name"
336
674
  }).trim()
337
675
  },
@@ -339,22 +677,22 @@ var commitSchema = z6.object(
339
677
  );
340
678
 
341
679
  // packages/models/src/lib/core-config.ts
342
- import { z as z12 } from "zod";
680
+ import { z as z13 } from "zod";
343
681
 
344
682
  // packages/models/src/lib/persist-config.ts
345
- import { z as z7 } from "zod";
346
- var formatSchema = z7.enum(["json", "md"]);
347
- var persistConfigSchema = z7.object({
683
+ import { z as z8 } from "zod";
684
+ var formatSchema = z8.enum(["json", "md"]);
685
+ var persistConfigSchema = z8.object({
348
686
  outputDir: filePathSchema.describe("Artifacts folder").optional(),
349
687
  filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
350
- format: z7.array(formatSchema).optional()
688
+ format: z8.array(formatSchema).optional()
351
689
  });
352
690
 
353
691
  // packages/models/src/lib/plugin-config.ts
354
- import { z as z10 } from "zod";
692
+ import { z as z11 } from "zod";
355
693
 
356
694
  // packages/models/src/lib/group.ts
357
- import { z as z8 } from "zod";
695
+ import { z as z9 } from "zod";
358
696
  var groupRefSchema = weightedRefSchema(
359
697
  "Weighted reference to a group",
360
698
  "Reference slug to a group within this plugin (e.g. 'max-lines')"
@@ -371,7 +709,7 @@ var groupSchema = scorableSchema(
371
709
  getDuplicateRefsInGroups,
372
710
  duplicateRefsInGroupsErrorMsg
373
711
  ).merge(groupMetaSchema);
374
- var groupsSchema = z8.array(groupSchema, {
712
+ var groupsSchema = z9.array(groupSchema, {
375
713
  description: "List of groups"
376
714
  }).optional().refine(
377
715
  (groups) => !getDuplicateSlugsInGroups(groups),
@@ -399,14 +737,14 @@ function getDuplicateSlugsInGroups(groups) {
399
737
  }
400
738
 
401
739
  // packages/models/src/lib/runner-config.ts
402
- import { z as z9 } from "zod";
403
- var outputTransformSchema = z9.function().args(z9.unknown()).returns(z9.union([auditOutputsSchema, z9.promise(auditOutputsSchema)]));
404
- var runnerConfigSchema = z9.object(
740
+ import { z as z10 } from "zod";
741
+ var outputTransformSchema = z10.function().args(z10.unknown()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
742
+ var runnerConfigSchema = z10.object(
405
743
  {
406
- command: z9.string({
744
+ command: z10.string({
407
745
  description: "Shell command to execute"
408
746
  }),
409
- args: z9.array(z9.string({ description: "Command arguments" })).optional(),
747
+ args: z10.array(z10.string({ description: "Command arguments" })).optional(),
410
748
  outputFile: filePathSchema.describe("Output path"),
411
749
  outputTransform: outputTransformSchema.optional()
412
750
  },
@@ -414,8 +752,8 @@ var runnerConfigSchema = z9.object(
414
752
  description: "How to execute runner"
415
753
  }
416
754
  );
417
- var onProgressSchema = z9.function().args(z9.unknown()).returns(z9.void());
418
- var runnerFunctionSchema = z9.function().args(onProgressSchema.optional()).returns(z9.union([auditOutputsSchema, z9.promise(auditOutputsSchema)]));
755
+ var onProgressSchema = z10.function().args(z10.unknown()).returns(z10.void());
756
+ var runnerFunctionSchema = z10.function().args(onProgressSchema.optional()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
419
757
 
420
758
  // packages/models/src/lib/plugin-config.ts
421
759
  var pluginMetaSchema = packageVersionSchema().merge(
@@ -426,13 +764,13 @@ var pluginMetaSchema = packageVersionSchema().merge(
426
764
  description: "Plugin metadata"
427
765
  })
428
766
  ).merge(
429
- z10.object({
767
+ z11.object({
430
768
  slug: slugSchema.describe("Unique plugin slug within core config"),
431
769
  icon: materialIconSchema
432
770
  })
433
771
  );
434
- var pluginDataSchema = z10.object({
435
- runner: z10.union([runnerConfigSchema, runnerFunctionSchema]),
772
+ var pluginDataSchema = z11.object({
773
+ runner: z11.union([runnerConfigSchema, runnerFunctionSchema]),
436
774
  audits: pluginAuditsSchema,
437
775
  groups: groupsSchema
438
776
  });
@@ -458,22 +796,22 @@ function getMissingRefsFromGroups(pluginCfg) {
458
796
  }
459
797
 
460
798
  // packages/models/src/lib/upload-config.ts
461
- import { z as z11 } from "zod";
462
- var uploadConfigSchema = z11.object({
799
+ import { z as z12 } from "zod";
800
+ var uploadConfigSchema = z12.object({
463
801
  server: urlSchema.describe("URL of deployed portal API"),
464
- apiKey: z11.string({
802
+ apiKey: z12.string({
465
803
  description: "API key with write access to portal (use `process.env` for security)"
466
804
  }),
467
805
  organization: slugSchema.describe(
468
806
  "Organization slug from Code PushUp portal"
469
807
  ),
470
808
  project: slugSchema.describe("Project slug from Code PushUp portal"),
471
- timeout: z11.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
809
+ timeout: z12.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
472
810
  });
473
811
 
474
812
  // packages/models/src/lib/core-config.ts
475
- var unrefinedCoreConfigSchema = z12.object({
476
- plugins: z12.array(pluginConfigSchema, {
813
+ var unrefinedCoreConfigSchema = z13.object({
814
+ plugins: z13.array(pluginConfigSchema, {
477
815
  description: "List of plugins to be used (official, community-provided, or custom)"
478
816
  }).min(1),
479
817
  /** portal configuration for persisting results */
@@ -496,7 +834,7 @@ function refineCoreConfig(schema) {
496
834
  }
497
835
 
498
836
  // packages/models/src/lib/report.ts
499
- import { z as z13 } from "zod";
837
+ import { z as z14 } from "zod";
500
838
  var auditReportSchema = auditSchema.merge(auditOutputSchema);
501
839
  var pluginReportSchema = pluginMetaSchema.merge(
502
840
  executionMetaSchema({
@@ -504,9 +842,9 @@ var pluginReportSchema = pluginMetaSchema.merge(
504
842
  descriptionDuration: "Duration of the plugin run in ms"
505
843
  })
506
844
  ).merge(
507
- z13.object({
508
- audits: z13.array(auditReportSchema).min(1),
509
- groups: z13.array(groupSchema).optional()
845
+ z14.object({
846
+ audits: z14.array(auditReportSchema).min(1),
847
+ groups: z14.array(groupSchema).optional()
510
848
  })
511
849
  ).refine(
512
850
  (pluginReport) => !getMissingRefsFromGroups2(pluginReport.audits, pluginReport.groups ?? []),
@@ -540,10 +878,10 @@ var reportSchema = packageVersionSchema({
540
878
  descriptionDuration: "Duration of the collect run in ms"
541
879
  })
542
880
  ).merge(
543
- z13.object(
881
+ z14.object(
544
882
  {
545
- categories: z13.array(categoryConfigSchema),
546
- plugins: z13.array(pluginReportSchema).min(1),
883
+ categories: z14.array(categoryConfigSchema),
884
+ plugins: z14.array(pluginReportSchema).min(1),
547
885
  commit: commitSchema.describe("Git commit for which report was collected").nullable()
548
886
  },
549
887
  { description: "Collect output data" }
@@ -559,40 +897,40 @@ var reportSchema = packageVersionSchema({
559
897
  );
560
898
 
561
899
  // packages/models/src/lib/reports-diff.ts
562
- import { z as z14 } from "zod";
900
+ import { z as z15 } from "zod";
563
901
  function makeComparisonSchema(schema) {
564
902
  const sharedDescription = schema.description || "Result";
565
- return z14.object({
903
+ return z15.object({
566
904
  before: schema.describe(`${sharedDescription} (source commit)`),
567
905
  after: schema.describe(`${sharedDescription} (target commit)`)
568
906
  });
569
907
  }
570
908
  function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
571
- return z14.object(
909
+ return z15.object(
572
910
  {
573
- changed: z14.array(diffSchema),
574
- unchanged: z14.array(resultSchema),
575
- added: z14.array(resultSchema),
576
- removed: z14.array(resultSchema)
911
+ changed: z15.array(diffSchema),
912
+ unchanged: z15.array(resultSchema),
913
+ added: z15.array(resultSchema),
914
+ removed: z15.array(resultSchema)
577
915
  },
578
916
  { description }
579
917
  );
580
918
  }
581
- var scorableMetaSchema = z14.object({
919
+ var scorableMetaSchema = z15.object({
582
920
  slug: slugSchema,
583
921
  title: titleSchema,
584
922
  docsUrl: docsUrlSchema
585
923
  });
586
924
  var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
587
- z14.object({
925
+ z15.object({
588
926
  plugin: pluginMetaSchema.pick({ slug: true, title: true, docsUrl: true }).describe("Plugin which defines it")
589
927
  })
590
928
  );
591
929
  var scorableDiffSchema = scorableMetaSchema.merge(
592
- z14.object({
930
+ z15.object({
593
931
  scores: makeComparisonSchema(scoreSchema).merge(
594
- z14.object({
595
- diff: z14.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
932
+ z15.object({
933
+ diff: z15.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
596
934
  })
597
935
  ).describe("Score comparison")
598
936
  })
@@ -603,10 +941,10 @@ var scorableWithPluginDiffSchema = scorableDiffSchema.merge(
603
941
  var categoryDiffSchema = scorableDiffSchema;
604
942
  var groupDiffSchema = scorableWithPluginDiffSchema;
605
943
  var auditDiffSchema = scorableWithPluginDiffSchema.merge(
606
- z14.object({
944
+ z15.object({
607
945
  values: makeComparisonSchema(auditValueSchema).merge(
608
- z14.object({
609
- diff: z14.number().int().describe("Value change (`values.after - values.before`)")
946
+ z15.object({
947
+ diff: z15.number().int().describe("Value change (`values.after - values.before`)")
610
948
  })
611
949
  ).describe("Audit `value` comparison"),
612
950
  displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
@@ -615,15 +953,15 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
615
953
  })
616
954
  );
617
955
  var categoryResultSchema = scorableMetaSchema.merge(
618
- z14.object({ score: scoreSchema })
956
+ z15.object({ score: scoreSchema })
619
957
  );
620
958
  var groupResultSchema = scorableWithPluginMetaSchema.merge(
621
- z14.object({ score: scoreSchema })
959
+ z15.object({ score: scoreSchema })
622
960
  );
623
961
  var auditResultSchema = scorableWithPluginMetaSchema.merge(
624
962
  auditOutputSchema.pick({ score: true, value: true, displayValue: true })
625
963
  );
626
- var reportsDiffSchema = z14.object({
964
+ var reportsDiffSchema = z15.object({
627
965
  commits: makeComparisonSchema(commitSchema).nullable().describe("Commits identifying compared reports"),
628
966
  categories: makeArraysComparisonSchema(
629
967
  categoryDiffSchema,
@@ -740,6 +1078,7 @@ function pluginWorkDir(slug) {
740
1078
  }
741
1079
 
742
1080
  // packages/utils/src/lib/reports/utils.ts
1081
+ var { image: image2, bold: boldMd } = md;
743
1082
  function calcDuration(start, stop) {
744
1083
  return Math.round((stop ?? performance.now()) - start);
745
1084
  }
@@ -775,13 +1114,13 @@ function executeProcess(cfg) {
775
1114
  process2.on("error", (err) => {
776
1115
  stderr += err.toString();
777
1116
  });
778
- process2.on("close", (code) => {
1117
+ process2.on("close", (code3) => {
779
1118
  const timings = { date, duration: calcDuration(start) };
780
- if (code === 0 || ignoreExitCode) {
1119
+ if (code3 === 0 || ignoreExitCode) {
781
1120
  onComplete?.();
782
- resolve({ code, stdout, stderr, ...timings });
1121
+ resolve({ code: code3, stdout, stderr, ...timings });
783
1122
  } else {
784
- const errorMsg = new ProcessError({ code, stdout, stderr, ...timings });
1123
+ const errorMsg = new ProcessError({ code: code3, stdout, stderr, ...timings });
785
1124
  onError?.(errorMsg);
786
1125
  reject(errorMsg);
787
1126
  }
@@ -789,39 +1128,47 @@ function executeProcess(cfg) {
789
1128
  });
790
1129
  }
791
1130
 
792
- // packages/utils/src/lib/git.ts
1131
+ // packages/utils/src/lib/git/git.ts
793
1132
  import { simpleGit } from "simple-git";
794
1133
 
795
- // packages/utils/src/lib/transform.ts
796
- import { platform } from "node:os";
797
- function objectToEntries(obj) {
798
- return Object.entries(obj);
799
- }
800
- function objectFromEntries(entries) {
801
- return Object.fromEntries(entries);
802
- }
803
- function toUnixNewlines(text) {
804
- return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
805
- }
806
- function fromJsonLines(jsonLines) {
807
- const unifiedNewLines = toUnixNewlines(jsonLines).trim();
808
- return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
809
- }
810
- function apostrophize(text, upperCase) {
811
- const lastCharMatch = text.match(/(\w)\W*$/);
812
- const lastChar = lastCharMatch?.[1] ?? "";
813
- return `${text}'${lastChar.toLocaleLowerCase() === "s" ? "" : upperCase ? "S" : "s"}`;
814
- }
1134
+ // packages/utils/src/lib/git/git.commits-and-tags.ts
1135
+ import { simpleGit as simpleGit2 } from "simple-git";
1136
+
1137
+ // packages/utils/src/lib/semver.ts
1138
+ import { rcompare, valid } from "semver";
815
1139
 
816
1140
  // packages/utils/src/lib/progress.ts
817
1141
  import chalk3 from "chalk";
818
1142
  import { MultiProgressBars } from "multi-progress-bars";
819
1143
 
1144
+ // packages/utils/src/lib/reports/formatting.ts
1145
+ var { headline: headline2, lines: lines2, link: link3, section: section2, table: table3 } = md;
1146
+
1147
+ // packages/utils/src/lib/reports/generate-md-report-categoy-section.ts
1148
+ var { link: link4, section: section3, h2: h22, lines: lines3, li: li2, bold: boldMd2, h3: h32, indentation: indentation2 } = md;
1149
+
1150
+ // packages/utils/src/lib/reports/generate-md-report.ts
1151
+ var { h1: h12, h2: h23, h3: h33, lines: lines4, link: link5, section: section4, code: codeMd } = md;
1152
+ var { bold: boldHtml, details: details2 } = html;
1153
+
1154
+ // packages/utils/src/lib/reports/generate-md-reports-diff.ts
1155
+ var {
1156
+ h1: h13,
1157
+ h2: h24,
1158
+ lines: lines5,
1159
+ link: link6,
1160
+ bold: boldMd3,
1161
+ italic: italicMd,
1162
+ table: table4,
1163
+ section: section5
1164
+ } = md;
1165
+ var { details: details3 } = html;
1166
+
820
1167
  // packages/utils/src/lib/reports/log-stdout-summary.ts
821
1168
  import chalk4 from "chalk";
822
1169
 
823
1170
  // packages/plugin-js-packages/src/lib/config.ts
824
- import { z as z15 } from "zod";
1171
+ import { z as z16 } from "zod";
825
1172
 
826
1173
  // packages/plugin-js-packages/src/lib/constants.ts
827
1174
  var defaultAuditLevelMapping = {
@@ -839,8 +1186,8 @@ var dependencyGroupToLong = {
839
1186
 
840
1187
  // packages/plugin-js-packages/src/lib/config.ts
841
1188
  var dependencyGroups = ["prod", "dev", "optional"];
842
- var packageCommandSchema = z15.enum(["audit", "outdated"]);
843
- var packageManagerIdSchema = z15.enum([
1189
+ var packageCommandSchema = z16.enum(["audit", "outdated"]);
1190
+ var packageManagerIdSchema = z16.enum([
844
1191
  "npm",
845
1192
  "yarn-classic",
846
1193
  "yarn-modern",
@@ -853,7 +1200,7 @@ var packageAuditLevels = [
853
1200
  "low",
854
1201
  "info"
855
1202
  ];
856
- var packageAuditLevelSchema = z15.enum(packageAuditLevels);
1203
+ var packageAuditLevelSchema = z16.enum(packageAuditLevels);
857
1204
  function fillAuditLevelMapping(mapping) {
858
1205
  return {
859
1206
  critical: mapping.critical ?? defaultAuditLevelMapping.critical,
@@ -863,14 +1210,14 @@ function fillAuditLevelMapping(mapping) {
863
1210
  info: mapping.info ?? defaultAuditLevelMapping.info
864
1211
  };
865
1212
  }
866
- var jsPackagesPluginConfigSchema = z15.object({
867
- checks: z15.array(packageCommandSchema, {
1213
+ var jsPackagesPluginConfigSchema = z16.object({
1214
+ checks: z16.array(packageCommandSchema, {
868
1215
  description: "Package manager commands to be run. Defaults to both audit and outdated."
869
1216
  }).min(1).default(["audit", "outdated"]),
870
1217
  packageManager: packageManagerIdSchema.describe(
871
1218
  "Package manager to be used."
872
1219
  ),
873
- auditLevelMapping: z15.record(packageAuditLevelSchema, issueSeveritySchema, {
1220
+ auditLevelMapping: z16.record(packageAuditLevelSchema, issueSeveritySchema, {
874
1221
  description: "Mapping of audit levels to issue severity. Custom mapping or overrides may be entered manually, otherwise has a default preset."
875
1222
  }).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping)
876
1223
  });
@@ -1168,17 +1515,73 @@ function validateYarnv1Result(result) {
1168
1515
  return [vulnerabilities, summary];
1169
1516
  }
1170
1517
 
1518
+ // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/constants.ts
1519
+ var outdatedtoFieldMapper = {
1520
+ name: "Package",
1521
+ current: "Current",
1522
+ latest: "Latest",
1523
+ type: "Package Type",
1524
+ url: "URL"
1525
+ };
1526
+ var REQUIRED_OUTDATED_FIELDS = [
1527
+ "Package",
1528
+ "Current",
1529
+ "Latest",
1530
+ "Package Type"
1531
+ ];
1532
+
1533
+ // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/types.ts
1534
+ var yarnv1FieldNames = [
1535
+ "Package",
1536
+ "Current",
1537
+ "Latest",
1538
+ "Package Type",
1539
+ "URL"
1540
+ ];
1541
+
1171
1542
  // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/outdated-result.ts
1172
1543
  function yarnv1ToOutdatedResult(output) {
1173
1544
  const yarnv1Outdated = fromJsonLines(output);
1545
+ const fields = yarnv1Outdated[1].data.head;
1174
1546
  const dependencies = yarnv1Outdated[1].data.body;
1175
- return dependencies.map(([name, current, _, latest, __, type, url]) => ({
1176
- name,
1177
- current,
1178
- latest,
1179
- type,
1180
- url
1181
- }));
1547
+ if (dependencies.length === 0) {
1548
+ return [];
1549
+ }
1550
+ validateOutdatedFields(fields);
1551
+ const indexMapping = getOutdatedFieldIndexes(fields);
1552
+ return dependencies.map(
1553
+ (dep) => objectFromEntries(
1554
+ objectToKeys(indexMapping).map((field) => [field, dep[indexMapping[field]]]).filter(
1555
+ (entry) => entry[1] != null
1556
+ )
1557
+ )
1558
+ );
1559
+ }
1560
+ function validateOutdatedFields(head) {
1561
+ const relevantFields = head.filter(isYarnv1FieldName);
1562
+ if (hasAllRequiredFields(relevantFields)) {
1563
+ return true;
1564
+ }
1565
+ throw new Error(
1566
+ `Yarn v1 outdated: Template [${head.join(
1567
+ ", "
1568
+ )}] does not contain all required fields [${yarnv1FieldNames.join(", ")}]`
1569
+ );
1570
+ }
1571
+ function isYarnv1FieldName(value) {
1572
+ const names = yarnv1FieldNames;
1573
+ return names.includes(value);
1574
+ }
1575
+ function hasAllRequiredFields(head) {
1576
+ return REQUIRED_OUTDATED_FIELDS.every((field) => head.includes(field));
1577
+ }
1578
+ function getOutdatedFieldIndexes(all) {
1579
+ return objectFromEntries(
1580
+ objectToEntries(outdatedtoFieldMapper).map(([outdatedField, yarnField]) => [
1581
+ outdatedField,
1582
+ all.indexOf(yarnField)
1583
+ ])
1584
+ );
1182
1585
  }
1183
1586
 
1184
1587
  // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/yarn-classic.ts
@@ -1344,7 +1747,7 @@ function vulnerabilitiesToIssues(vulnerabilities, auditLevelMapping) {
1344
1747
  }
1345
1748
  return vulnerabilities.map((detail) => {
1346
1749
  const versionRange = detail.versionRange === "*" ? "**all** versions" : `versions **${detail.versionRange}**`;
1347
- const directDependency = typeof detail.directDependency === "string" ? `\`${detail.directDependency}\`` : "";
1750
+ const directDependency = typeof detail.directDependency === "string" && detail.directDependency !== "" ? `\`${detail.directDependency}\`` : "";
1348
1751
  const depHierarchy = directDependency === "" ? `\`${detail.name}\` dependency` : `${apostrophize(directDependency)} dependency \`${detail.name}\``;
1349
1752
  const vulnerabilitySummary = `has a **${detail.severity}** vulnerability in ${versionRange}.`;
1350
1753
  const fixInfo = detail.fixInformation ? ` ${detail.fixInformation}` : "";
@@ -1366,31 +1769,43 @@ var PLUGIN_CONFIG_PATH = join2(
1366
1769
  "plugin-config.json"
1367
1770
  );
1368
1771
 
1772
+ // packages/plugin-js-packages/src/lib/runner/outdated/transform.ts
1773
+ import { clean, diff, neq } from "semver";
1774
+
1369
1775
  // packages/plugin-js-packages/src/lib/runner/outdated/constants.ts
1370
1776
  var outdatedSeverity = {
1371
1777
  major: "error",
1778
+ premajor: "info",
1372
1779
  minor: "warning",
1373
- patch: "info"
1780
+ preminor: "info",
1781
+ patch: "info",
1782
+ prepatch: "info",
1783
+ prerelease: "info"
1374
1784
  };
1375
-
1376
- // packages/plugin-js-packages/src/lib/runner/outdated/types.ts
1377
- var versionType = ["major", "minor", "patch"];
1785
+ var RELEASE_TYPES = objectToKeys(outdatedSeverity);
1378
1786
 
1379
1787
  // packages/plugin-js-packages/src/lib/runner/outdated/transform.ts
1380
1788
  function outdatedResultToAuditOutput(result, packageManager, depGroup) {
1381
1789
  const relevantDependencies = result.filter(
1382
1790
  (dep) => dep.type === dependencyGroupToLong[depGroup]
1383
1791
  );
1384
- const outdatedDependencies = relevantDependencies.filter((dep) => dep.current !== dep.latest).filter(
1385
- (dep) => dep.current.split("-")[0]?.toString() !== dep.latest.split("-")[0]?.toString()
1792
+ const validDependencies = relevantDependencies.map((dep) => ({
1793
+ ...dep,
1794
+ current: clean(dep.current),
1795
+ latest: clean(dep.latest)
1796
+ })).filter(
1797
+ (dep) => dep.current != null && dep.latest != null
1386
1798
  );
1387
- const outdatedStats = outdatedDependencies.reduce(
1388
- (acc, dep) => {
1389
- const outdatedLevel = getOutdatedLevel(dep.current, dep.latest);
1390
- return { ...acc, [outdatedLevel]: acc[outdatedLevel] + 1 };
1391
- },
1392
- { major: 0, minor: 0, patch: 0 }
1799
+ const outdatedDependencies = validDependencies.filter(
1800
+ (dep) => neq(dep.current, dep.latest)
1393
1801
  );
1802
+ const outdatedStats = outdatedDependencies.reduce((acc, dep) => {
1803
+ const outdatedLevel = diff(dep.current, dep.latest);
1804
+ if (outdatedLevel == null) {
1805
+ return acc;
1806
+ }
1807
+ return { ...acc, [outdatedLevel]: acc[outdatedLevel] + 1 };
1808
+ }, objectFromEntries(RELEASE_TYPES.map((versionType) => [versionType, 0])));
1394
1809
  const issues = outdatedDependencies.length === 0 ? [] : outdatedToIssues(outdatedDependencies);
1395
1810
  return {
1396
1811
  slug: `${packageManager}-outdated-${depGroup}`,
@@ -1407,8 +1822,10 @@ function calculateOutdatedScore(majorOutdated, totalDeps) {
1407
1822
  return totalDeps > 0 ? (totalDeps - majorOutdated) / totalDeps : 1;
1408
1823
  }
1409
1824
  function outdatedToDisplayValue(stats) {
1410
- const total = stats.major + stats.minor + stats.patch;
1411
- const versionBreakdown = versionType.map((version) => stats[version] > 0 ? `${stats[version]} ${version}` : "").filter((text) => text !== "");
1825
+ const total = Object.values(stats).reduce((acc, value) => acc + value, 0);
1826
+ const versionBreakdown = RELEASE_TYPES.map(
1827
+ (version) => stats[version] > 0 ? `${stats[version]} ${version}` : ""
1828
+ ).filter((text) => text !== "");
1412
1829
  if (versionBreakdown.length === 0) {
1413
1830
  return "all dependencies are up to date";
1414
1831
  }
@@ -1425,7 +1842,7 @@ function outdatedToDisplayValue(stats) {
1425
1842
  function outdatedToIssues(dependencies) {
1426
1843
  return dependencies.map((dep) => {
1427
1844
  const { name, current, latest, url } = dep;
1428
- const outdatedLevel = getOutdatedLevel(current, latest);
1845
+ const outdatedLevel = diff(current, latest);
1429
1846
  const packageReference = url == null ? `\`${name}\`` : `[\`${name}\`](${url})`;
1430
1847
  return {
1431
1848
  message: `Package ${packageReference} requires a **${outdatedLevel}** update from **${current}** to **${latest}**.`,
@@ -1433,28 +1850,6 @@ function outdatedToIssues(dependencies) {
1433
1850
  };
1434
1851
  });
1435
1852
  }
1436
- function getOutdatedLevel(currentFullVersion, latestFullVersion) {
1437
- const current = splitPackageVersion(currentFullVersion);
1438
- const latest = splitPackageVersion(latestFullVersion);
1439
- if (current.major < latest.major) {
1440
- return "major";
1441
- }
1442
- if (current.minor < latest.minor) {
1443
- return "minor";
1444
- }
1445
- if (current.patch < latest.patch) {
1446
- return "patch";
1447
- }
1448
- throw new Error("Package is not outdated.");
1449
- }
1450
- function splitPackageVersion(fullVersion) {
1451
- const semanticVersion = String(fullVersion.split("-")[0]);
1452
- const [major, minor, patch] = semanticVersion.split(".").map(Number);
1453
- if (major == null || minor == null || patch == null) {
1454
- throw new Error(`Invalid version description ${fullVersion}`);
1455
- }
1456
- return { major, minor, patch };
1457
- }
1458
1853
 
1459
1854
  // packages/plugin-js-packages/src/lib/runner/index.ts
1460
1855
  async function executeRunner() {