@code-pushup/js-packages-plugin 0.39.0 → 0.42.1

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
@@ -4,13 +4,10 @@ import { fileURLToPath } from "node:url";
4
4
 
5
5
  // packages/plugin-js-packages/package.json
6
6
  var name = "@code-pushup/js-packages-plugin";
7
- var version = "0.39.0";
7
+ var version = "0.42.1";
8
8
 
9
9
  // packages/plugin-js-packages/src/lib/config.ts
10
- import { z as z15 } from "zod";
11
-
12
- // packages/models/src/lib/audit.ts
13
- import { z as z2 } from "zod";
10
+ import { z as z16 } from "zod";
14
11
 
15
12
  // packages/models/src/lib/implementation/schemas.ts
16
13
  import { MATERIAL_ICONS } from "vscode-material-icons";
@@ -77,6 +74,7 @@ function missingRefsForCategoriesErrorMsg(categories, plugins) {
77
74
  }
78
75
 
79
76
  // packages/models/src/lib/implementation/schemas.ts
77
+ var primitiveValueSchema = z.union([z.string(), z.number()]);
80
78
  function executionMetaSchema(options = {
81
79
  descriptionDate: "Execution start date and time",
82
80
  descriptionDuration: "Execution duration in ms"
@@ -168,6 +166,7 @@ function hasNonZeroWeightedRef(refs) {
168
166
  }
169
167
 
170
168
  // packages/models/src/lib/audit.ts
169
+ import { z as z2 } from "zod";
171
170
  var auditSchema = z2.object({
172
171
  slug: slugSchema.describe("ID (unique within plugin)")
173
172
  }).merge(
@@ -197,7 +196,7 @@ function getDuplicateSlugsInAudits(audits) {
197
196
  }
198
197
 
199
198
  // packages/models/src/lib/audit-output.ts
200
- import { z as z4 } from "zod";
199
+ import { z as z5 } from "zod";
201
200
 
202
201
  // packages/models/src/lib/issue.ts
203
202
  import { z as z3 } from "zod";
@@ -228,16 +227,61 @@ var issueSchema = z3.object(
228
227
  { description: "Issue information" }
229
228
  );
230
229
 
230
+ // packages/models/src/lib/table.ts
231
+ import { z as z4 } from "zod";
232
+ var tableAlignmentSchema = z4.enum(["left", "center", "right"], {
233
+ description: "Cell alignment"
234
+ });
235
+ var tableColumnObjectSchema = z4.object({
236
+ key: z4.string(),
237
+ label: z4.string().optional(),
238
+ align: tableAlignmentSchema.optional()
239
+ });
240
+ var tableRowObjectSchema = z4.record(primitiveValueSchema, {
241
+ description: "Object row"
242
+ });
243
+ var tableRowPrimitiveSchema = z4.array(primitiveValueSchema, {
244
+ description: "Primitive row"
245
+ });
246
+ var tableSharedSchema = z4.object({
247
+ title: z4.string().optional().describe("Display title for table")
248
+ });
249
+ var tablePrimitiveSchema = tableSharedSchema.merge(
250
+ z4.object(
251
+ {
252
+ columns: z4.array(tableAlignmentSchema).optional(),
253
+ rows: z4.array(tableRowPrimitiveSchema)
254
+ },
255
+ { description: "Table with primitive rows and optional alignment columns" }
256
+ )
257
+ );
258
+ var tableObjectSchema = tableSharedSchema.merge(
259
+ z4.object(
260
+ {
261
+ columns: z4.union([
262
+ z4.array(tableAlignmentSchema),
263
+ z4.array(tableColumnObjectSchema)
264
+ ]).optional(),
265
+ rows: z4.array(tableRowObjectSchema)
266
+ },
267
+ {
268
+ description: "Table with object rows and optional alignment or object columns"
269
+ }
270
+ )
271
+ );
272
+ var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
273
+
231
274
  // packages/models/src/lib/audit-output.ts
232
275
  var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
233
- var auditDisplayValueSchema = z4.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
234
- var auditDetailsSchema = z4.object(
276
+ var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
277
+ var auditDetailsSchema = z5.object(
235
278
  {
236
- issues: z4.array(issueSchema, { description: "List of findings" })
279
+ issues: z5.array(issueSchema, { description: "List of findings" }).optional(),
280
+ table: tableSchema("Table of related findings").optional()
237
281
  },
238
282
  { description: "Detailed information" }
239
283
  );
240
- var auditOutputSchema = z4.object(
284
+ var auditOutputSchema = z5.object(
241
285
  {
242
286
  slug: slugSchema.describe("Reference to audit"),
243
287
  displayValue: auditDisplayValueSchema,
@@ -247,7 +291,7 @@ var auditOutputSchema = z4.object(
247
291
  },
248
292
  { description: "Audit information" }
249
293
  );
250
- var auditOutputsSchema = z4.array(auditOutputSchema, {
294
+ var auditOutputsSchema = z5.array(auditOutputSchema, {
251
295
  description: "List of JSON formatted audit output emitted by the runner process of a plugin"
252
296
  }).refine(
253
297
  (audits) => !getDuplicateSlugsInAudits2(audits),
@@ -264,13 +308,13 @@ function getDuplicateSlugsInAudits2(audits) {
264
308
  }
265
309
 
266
310
  // packages/models/src/lib/category-config.ts
267
- import { z as z5 } from "zod";
311
+ import { z as z6 } from "zod";
268
312
  var categoryRefSchema = weightedRefSchema(
269
313
  "Weighted references to audits and/or groups for the category",
270
314
  "Slug of an audit or group (depending on `type`)"
271
315
  ).merge(
272
- z5.object({
273
- type: z5.enum(["audit", "group"], {
316
+ z6.object({
317
+ type: z6.enum(["audit", "group"], {
274
318
  description: "Discriminant for reference kind, affects where `slug` is looked up"
275
319
  }),
276
320
  plugin: slugSchema.describe(
@@ -291,8 +335,8 @@ var categoryConfigSchema = scorableSchema(
291
335
  description: "Meta info for category"
292
336
  })
293
337
  ).merge(
294
- z5.object({
295
- isBinary: z5.boolean({
338
+ z6.object({
339
+ isBinary: z6.boolean({
296
340
  description: 'Is this a binary category (i.e. only a perfect score considered a "pass")?'
297
341
  }).optional()
298
342
  })
@@ -308,7 +352,7 @@ function getDuplicateRefsInCategoryMetrics(metrics) {
308
352
  metrics.map(({ slug, type, plugin }) => `${type} :: ${plugin} / ${slug}`)
309
353
  );
310
354
  }
311
- var categoriesSchema = z5.array(categoryConfigSchema, {
355
+ var categoriesSchema = z6.array(categoryConfigSchema, {
312
356
  description: "Categorization of individual audits"
313
357
  }).refine(
314
358
  (categoryCfg) => !getDuplicateSlugCategories(categoryCfg),
@@ -327,18 +371,18 @@ function getDuplicateSlugCategories(categories) {
327
371
  }
328
372
 
329
373
  // packages/models/src/lib/commit.ts
330
- import { z as z6 } from "zod";
331
- var commitSchema = z6.object(
374
+ import { z as z7 } from "zod";
375
+ var commitSchema = z7.object(
332
376
  {
333
- hash: z6.string({ description: "Commit SHA (full)" }).regex(
377
+ hash: z7.string({ description: "Commit SHA (full)" }).regex(
334
378
  /^[\da-f]{40}$/,
335
379
  "Commit SHA should be a 40-character hexadecimal string"
336
380
  ),
337
- message: z6.string({ description: "Commit message" }),
338
- date: z6.coerce.date({
381
+ message: z7.string({ description: "Commit message" }),
382
+ date: z7.coerce.date({
339
383
  description: "Date and time when commit was authored"
340
384
  }),
341
- author: z6.string({
385
+ author: z7.string({
342
386
  description: "Commit author name"
343
387
  }).trim()
344
388
  },
@@ -346,22 +390,22 @@ var commitSchema = z6.object(
346
390
  );
347
391
 
348
392
  // packages/models/src/lib/core-config.ts
349
- import { z as z12 } from "zod";
393
+ import { z as z13 } from "zod";
350
394
 
351
395
  // packages/models/src/lib/persist-config.ts
352
- import { z as z7 } from "zod";
353
- var formatSchema = z7.enum(["json", "md"]);
354
- var persistConfigSchema = z7.object({
396
+ import { z as z8 } from "zod";
397
+ var formatSchema = z8.enum(["json", "md"]);
398
+ var persistConfigSchema = z8.object({
355
399
  outputDir: filePathSchema.describe("Artifacts folder").optional(),
356
400
  filename: fileNameSchema.describe("Artifacts file name (without extension)").optional(),
357
- format: z7.array(formatSchema).optional()
401
+ format: z8.array(formatSchema).optional()
358
402
  });
359
403
 
360
404
  // packages/models/src/lib/plugin-config.ts
361
- import { z as z10 } from "zod";
405
+ import { z as z11 } from "zod";
362
406
 
363
407
  // packages/models/src/lib/group.ts
364
- import { z as z8 } from "zod";
408
+ import { z as z9 } from "zod";
365
409
  var groupRefSchema = weightedRefSchema(
366
410
  "Weighted reference to a group",
367
411
  "Reference slug to a group within this plugin (e.g. 'max-lines')"
@@ -378,7 +422,7 @@ var groupSchema = scorableSchema(
378
422
  getDuplicateRefsInGroups,
379
423
  duplicateRefsInGroupsErrorMsg
380
424
  ).merge(groupMetaSchema);
381
- var groupsSchema = z8.array(groupSchema, {
425
+ var groupsSchema = z9.array(groupSchema, {
382
426
  description: "List of groups"
383
427
  }).optional().refine(
384
428
  (groups) => !getDuplicateSlugsInGroups(groups),
@@ -406,14 +450,14 @@ function getDuplicateSlugsInGroups(groups) {
406
450
  }
407
451
 
408
452
  // packages/models/src/lib/runner-config.ts
409
- import { z as z9 } from "zod";
410
- var outputTransformSchema = z9.function().args(z9.unknown()).returns(z9.union([auditOutputsSchema, z9.promise(auditOutputsSchema)]));
411
- var runnerConfigSchema = z9.object(
453
+ import { z as z10 } from "zod";
454
+ var outputTransformSchema = z10.function().args(z10.unknown()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
455
+ var runnerConfigSchema = z10.object(
412
456
  {
413
- command: z9.string({
457
+ command: z10.string({
414
458
  description: "Shell command to execute"
415
459
  }),
416
- args: z9.array(z9.string({ description: "Command arguments" })).optional(),
460
+ args: z10.array(z10.string({ description: "Command arguments" })).optional(),
417
461
  outputFile: filePathSchema.describe("Output path"),
418
462
  outputTransform: outputTransformSchema.optional()
419
463
  },
@@ -421,8 +465,8 @@ var runnerConfigSchema = z9.object(
421
465
  description: "How to execute runner"
422
466
  }
423
467
  );
424
- var onProgressSchema = z9.function().args(z9.unknown()).returns(z9.void());
425
- var runnerFunctionSchema = z9.function().args(onProgressSchema.optional()).returns(z9.union([auditOutputsSchema, z9.promise(auditOutputsSchema)]));
468
+ var onProgressSchema = z10.function().args(z10.unknown()).returns(z10.void());
469
+ var runnerFunctionSchema = z10.function().args(onProgressSchema.optional()).returns(z10.union([auditOutputsSchema, z10.promise(auditOutputsSchema)]));
426
470
 
427
471
  // packages/models/src/lib/plugin-config.ts
428
472
  var pluginMetaSchema = packageVersionSchema().merge(
@@ -433,13 +477,13 @@ var pluginMetaSchema = packageVersionSchema().merge(
433
477
  description: "Plugin metadata"
434
478
  })
435
479
  ).merge(
436
- z10.object({
480
+ z11.object({
437
481
  slug: slugSchema.describe("Unique plugin slug within core config"),
438
482
  icon: materialIconSchema
439
483
  })
440
484
  );
441
- var pluginDataSchema = z10.object({
442
- runner: z10.union([runnerConfigSchema, runnerFunctionSchema]),
485
+ var pluginDataSchema = z11.object({
486
+ runner: z11.union([runnerConfigSchema, runnerFunctionSchema]),
443
487
  audits: pluginAuditsSchema,
444
488
  groups: groupsSchema
445
489
  });
@@ -465,22 +509,22 @@ function getMissingRefsFromGroups(pluginCfg) {
465
509
  }
466
510
 
467
511
  // packages/models/src/lib/upload-config.ts
468
- import { z as z11 } from "zod";
469
- var uploadConfigSchema = z11.object({
512
+ import { z as z12 } from "zod";
513
+ var uploadConfigSchema = z12.object({
470
514
  server: urlSchema.describe("URL of deployed portal API"),
471
- apiKey: z11.string({
515
+ apiKey: z12.string({
472
516
  description: "API key with write access to portal (use `process.env` for security)"
473
517
  }),
474
518
  organization: slugSchema.describe(
475
519
  "Organization slug from Code PushUp portal"
476
520
  ),
477
521
  project: slugSchema.describe("Project slug from Code PushUp portal"),
478
- timeout: z11.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
522
+ timeout: z12.number({ description: "Request timeout in minutes (default is 5)" }).positive().int().optional()
479
523
  });
480
524
 
481
525
  // packages/models/src/lib/core-config.ts
482
- var unrefinedCoreConfigSchema = z12.object({
483
- plugins: z12.array(pluginConfigSchema, {
526
+ var unrefinedCoreConfigSchema = z13.object({
527
+ plugins: z13.array(pluginConfigSchema, {
484
528
  description: "List of plugins to be used (official, community-provided, or custom)"
485
529
  }).min(1),
486
530
  /** portal configuration for persisting results */
@@ -503,7 +547,7 @@ function refineCoreConfig(schema) {
503
547
  }
504
548
 
505
549
  // packages/models/src/lib/report.ts
506
- import { z as z13 } from "zod";
550
+ import { z as z14 } from "zod";
507
551
  var auditReportSchema = auditSchema.merge(auditOutputSchema);
508
552
  var pluginReportSchema = pluginMetaSchema.merge(
509
553
  executionMetaSchema({
@@ -511,9 +555,9 @@ var pluginReportSchema = pluginMetaSchema.merge(
511
555
  descriptionDuration: "Duration of the plugin run in ms"
512
556
  })
513
557
  ).merge(
514
- z13.object({
515
- audits: z13.array(auditReportSchema).min(1),
516
- groups: z13.array(groupSchema).optional()
558
+ z14.object({
559
+ audits: z14.array(auditReportSchema).min(1),
560
+ groups: z14.array(groupSchema).optional()
517
561
  })
518
562
  ).refine(
519
563
  (pluginReport) => !getMissingRefsFromGroups2(pluginReport.audits, pluginReport.groups ?? []),
@@ -547,10 +591,10 @@ var reportSchema = packageVersionSchema({
547
591
  descriptionDuration: "Duration of the collect run in ms"
548
592
  })
549
593
  ).merge(
550
- z13.object(
594
+ z14.object(
551
595
  {
552
- categories: z13.array(categoryConfigSchema),
553
- plugins: z13.array(pluginReportSchema).min(1),
596
+ categories: z14.array(categoryConfigSchema),
597
+ plugins: z14.array(pluginReportSchema).min(1),
554
598
  commit: commitSchema.describe("Git commit for which report was collected").nullable()
555
599
  },
556
600
  { description: "Collect output data" }
@@ -566,40 +610,40 @@ var reportSchema = packageVersionSchema({
566
610
  );
567
611
 
568
612
  // packages/models/src/lib/reports-diff.ts
569
- import { z as z14 } from "zod";
613
+ import { z as z15 } from "zod";
570
614
  function makeComparisonSchema(schema) {
571
615
  const sharedDescription = schema.description || "Result";
572
- return z14.object({
616
+ return z15.object({
573
617
  before: schema.describe(`${sharedDescription} (source commit)`),
574
618
  after: schema.describe(`${sharedDescription} (target commit)`)
575
619
  });
576
620
  }
577
621
  function makeArraysComparisonSchema(diffSchema, resultSchema, description) {
578
- return z14.object(
622
+ return z15.object(
579
623
  {
580
- changed: z14.array(diffSchema),
581
- unchanged: z14.array(resultSchema),
582
- added: z14.array(resultSchema),
583
- removed: z14.array(resultSchema)
624
+ changed: z15.array(diffSchema),
625
+ unchanged: z15.array(resultSchema),
626
+ added: z15.array(resultSchema),
627
+ removed: z15.array(resultSchema)
584
628
  },
585
629
  { description }
586
630
  );
587
631
  }
588
- var scorableMetaSchema = z14.object({
632
+ var scorableMetaSchema = z15.object({
589
633
  slug: slugSchema,
590
634
  title: titleSchema,
591
635
  docsUrl: docsUrlSchema
592
636
  });
593
637
  var scorableWithPluginMetaSchema = scorableMetaSchema.merge(
594
- z14.object({
638
+ z15.object({
595
639
  plugin: pluginMetaSchema.pick({ slug: true, title: true, docsUrl: true }).describe("Plugin which defines it")
596
640
  })
597
641
  );
598
642
  var scorableDiffSchema = scorableMetaSchema.merge(
599
- z14.object({
643
+ z15.object({
600
644
  scores: makeComparisonSchema(scoreSchema).merge(
601
- z14.object({
602
- diff: z14.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
645
+ z15.object({
646
+ diff: z15.number().min(-1).max(1).describe("Score change (`scores.after - scores.before`)")
603
647
  })
604
648
  ).describe("Score comparison")
605
649
  })
@@ -610,10 +654,10 @@ var scorableWithPluginDiffSchema = scorableDiffSchema.merge(
610
654
  var categoryDiffSchema = scorableDiffSchema;
611
655
  var groupDiffSchema = scorableWithPluginDiffSchema;
612
656
  var auditDiffSchema = scorableWithPluginDiffSchema.merge(
613
- z14.object({
657
+ z15.object({
614
658
  values: makeComparisonSchema(auditValueSchema).merge(
615
- z14.object({
616
- diff: z14.number().int().describe("Value change (`values.after - values.before`)")
659
+ z15.object({
660
+ diff: z15.number().int().describe("Value change (`values.after - values.before`)")
617
661
  })
618
662
  ).describe("Audit `value` comparison"),
619
663
  displayValues: makeComparisonSchema(auditDisplayValueSchema).describe(
@@ -622,15 +666,15 @@ var auditDiffSchema = scorableWithPluginDiffSchema.merge(
622
666
  })
623
667
  );
624
668
  var categoryResultSchema = scorableMetaSchema.merge(
625
- z14.object({ score: scoreSchema })
669
+ z15.object({ score: scoreSchema })
626
670
  );
627
671
  var groupResultSchema = scorableWithPluginMetaSchema.merge(
628
- z14.object({ score: scoreSchema })
672
+ z15.object({ score: scoreSchema })
629
673
  );
630
674
  var auditResultSchema = scorableWithPluginMetaSchema.merge(
631
675
  auditOutputSchema.pick({ score: true, value: true, displayValue: true })
632
676
  );
633
- var reportsDiffSchema = z14.object({
677
+ var reportsDiffSchema = z15.object({
634
678
  commits: makeComparisonSchema(commitSchema).nullable().describe("Commits identifying compared reports"),
635
679
  categories: makeArraysComparisonSchema(
636
680
  categoryDiffSchema,
@@ -686,8 +730,8 @@ var dependencyDocs = {
686
730
 
687
731
  // packages/plugin-js-packages/src/lib/config.ts
688
732
  var dependencyGroups = ["prod", "dev", "optional"];
689
- var packageCommandSchema = z15.enum(["audit", "outdated"]);
690
- var packageManagerIdSchema = z15.enum([
733
+ var packageCommandSchema = z16.enum(["audit", "outdated"]);
734
+ var packageManagerIdSchema = z16.enum([
691
735
  "npm",
692
736
  "yarn-classic",
693
737
  "yarn-modern",
@@ -700,7 +744,7 @@ var packageAuditLevels = [
700
744
  "low",
701
745
  "info"
702
746
  ];
703
- var packageAuditLevelSchema = z15.enum(packageAuditLevels);
747
+ var packageAuditLevelSchema = z16.enum(packageAuditLevels);
704
748
  function fillAuditLevelMapping(mapping) {
705
749
  return {
706
750
  critical: mapping.critical ?? defaultAuditLevelMapping.critical,
@@ -710,14 +754,14 @@ function fillAuditLevelMapping(mapping) {
710
754
  info: mapping.info ?? defaultAuditLevelMapping.info
711
755
  };
712
756
  }
713
- var jsPackagesPluginConfigSchema = z15.object({
714
- checks: z15.array(packageCommandSchema, {
757
+ var jsPackagesPluginConfigSchema = z16.object({
758
+ checks: z16.array(packageCommandSchema, {
715
759
  description: "Package manager commands to be run. Defaults to both audit and outdated."
716
760
  }).min(1).default(["audit", "outdated"]),
717
761
  packageManager: packageManagerIdSchema.describe(
718
762
  "Package manager to be used."
719
763
  ),
720
- auditLevelMapping: z15.record(packageAuditLevelSchema, issueSeveritySchema, {
764
+ auditLevelMapping: z16.record(packageAuditLevelSchema, issueSeveritySchema, {
721
765
  description: "Mapping of audit levels to issue severity. Custom mapping or overrides may be entered manually, otherwise has a default preset."
722
766
  }).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping)
723
767
  });
@@ -758,6 +802,295 @@ function filterAuditResult(result, key, referenceResult) {
758
802
  var COMMON_AUDIT_ARGS = ["audit", "--json"];
759
803
  var COMMON_OUTDATED_ARGS = ["outdated", "--json"];
760
804
 
805
+ // packages/utils/src/lib/text-formats/constants.ts
806
+ var NEW_LINE = "\n";
807
+ var TAB = " ";
808
+
809
+ // packages/utils/src/lib/text-formats/html/details.ts
810
+ function details(title, content, cfg = { open: false }) {
811
+ 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.
812
+ NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
813
+ // ⚠️ The blank line ensure Markdown in content is rendered correctly.
814
+ NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
815
+ NEW_LINE}`;
816
+ }
817
+
818
+ // packages/utils/src/lib/text-formats/html/font-style.ts
819
+ var boldElement = "b";
820
+ function bold(text) {
821
+ return `<${boldElement}>${text}</${boldElement}>`;
822
+ }
823
+ var italicElement = "i";
824
+ function italic(text) {
825
+ return `<${italicElement}>${text}</${italicElement}>`;
826
+ }
827
+ var codeElement = "code";
828
+ function code(text) {
829
+ return `<${codeElement}>${text}</${codeElement}>`;
830
+ }
831
+
832
+ // packages/utils/src/lib/text-formats/html/link.ts
833
+ function link(href, text) {
834
+ return `<a href="${href}">${text || href}"</a>`;
835
+ }
836
+
837
+ // packages/utils/src/lib/transform.ts
838
+ import { platform } from "node:os";
839
+ function objectToKeys(obj) {
840
+ return Object.keys(obj);
841
+ }
842
+ function objectToEntries(obj) {
843
+ return Object.entries(obj);
844
+ }
845
+ function objectFromEntries(entries) {
846
+ return Object.fromEntries(entries);
847
+ }
848
+ function toUnixNewlines(text) {
849
+ return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
850
+ }
851
+ function fromJsonLines(jsonLines) {
852
+ const unifiedNewLines = toUnixNewlines(jsonLines).trim();
853
+ return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
854
+ }
855
+ function capitalize(text) {
856
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
857
+ 1
858
+ )}`;
859
+ }
860
+
861
+ // packages/utils/src/lib/table.ts
862
+ function rowToStringArray({ rows, columns = [] }) {
863
+ if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
864
+ throw new TypeError(
865
+ "Column can`t be object when rows are primitive values"
866
+ );
867
+ }
868
+ return rows.map((row) => {
869
+ if (Array.isArray(row)) {
870
+ return row.map(String);
871
+ }
872
+ const objectRow = row;
873
+ if (columns.length === 0 || typeof columns.at(0) === "string") {
874
+ return Object.values(objectRow).map(String);
875
+ }
876
+ return columns.map(
877
+ ({ key }) => String(objectRow[key])
878
+ );
879
+ });
880
+ }
881
+ function columnsToStringArray({ rows, columns = [] }) {
882
+ const firstRow = rows.at(0);
883
+ const primitiveRows = Array.isArray(firstRow);
884
+ if (typeof columns.at(0) === "string" && !primitiveRows) {
885
+ throw new Error("invalid union type. Caught by model parsing.");
886
+ }
887
+ if (columns.length === 0) {
888
+ if (Array.isArray(firstRow)) {
889
+ return firstRow.map((_, idx) => String(idx));
890
+ }
891
+ return Object.keys(firstRow);
892
+ }
893
+ if (typeof columns.at(0) === "string") {
894
+ return columns.map(String);
895
+ }
896
+ const cols = columns;
897
+ return cols.map(({ label, key }) => label ?? capitalize(key));
898
+ }
899
+ function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
900
+ const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
901
+ if (typeof column === "string") {
902
+ return column;
903
+ } else if (typeof column === "object") {
904
+ return column.align ?? "center";
905
+ } else {
906
+ return "center";
907
+ }
908
+ }
909
+ function getColumnAlignmentForIndex(targetIdx, columns = []) {
910
+ const column = columns.at(targetIdx);
911
+ if (column == null) {
912
+ return "center";
913
+ } else if (typeof column === "string") {
914
+ return column;
915
+ } else if (typeof column === "object") {
916
+ return column.align ?? "center";
917
+ } else {
918
+ return "center";
919
+ }
920
+ }
921
+ function getColumnAlignments({
922
+ rows,
923
+ columns = []
924
+ }) {
925
+ if (rows.at(0) == null) {
926
+ throw new Error("first row can`t be undefined.");
927
+ }
928
+ if (Array.isArray(rows.at(0))) {
929
+ const firstPrimitiveRow = rows.at(0);
930
+ return Array.from({ length: firstPrimitiveRow.length }).map(
931
+ (_, idx) => getColumnAlignmentForIndex(idx, columns)
932
+ );
933
+ }
934
+ const firstObject = rows.at(0);
935
+ return Object.keys(firstObject).map(
936
+ (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
937
+ );
938
+ }
939
+
940
+ // packages/utils/src/lib/text-formats/html/table.ts
941
+ function wrap(elem, content) {
942
+ return `<${elem}>${content}</${elem}>${NEW_LINE}`;
943
+ }
944
+ function wrapRow(content) {
945
+ const elem = "tr";
946
+ return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
947
+ }
948
+ function table(tableData) {
949
+ if (tableData.rows.length === 0) {
950
+ throw new Error("Data can't be empty");
951
+ }
952
+ const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
953
+ const tableHeaderRow = wrapRow(tableHeaderCols);
954
+ const tableBody = rowToStringArray(tableData).map((arr) => {
955
+ const columns = arr.map((s) => wrap("td", s)).join("");
956
+ return wrapRow(columns);
957
+ }).join("");
958
+ return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
959
+ }
960
+
961
+ // packages/utils/src/lib/text-formats/md/font-style.ts
962
+ var boldWrap = "**";
963
+ function bold2(text) {
964
+ return `${boldWrap}${text}${boldWrap}`;
965
+ }
966
+ var italicWrap = "_";
967
+ function italic2(text) {
968
+ return `${italicWrap}${text}${italicWrap}`;
969
+ }
970
+ var strikeThroughWrap = "~";
971
+ function strikeThrough(text) {
972
+ return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
973
+ }
974
+ var codeWrap = "`";
975
+ function code2(text) {
976
+ return `${codeWrap}${text}${codeWrap}`;
977
+ }
978
+
979
+ // packages/utils/src/lib/text-formats/md/headline.ts
980
+ function headline(text, hierarchy = 1) {
981
+ return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
982
+ }
983
+ function h(text, hierarchy = 1) {
984
+ return headline(text, hierarchy);
985
+ }
986
+ function h1(text) {
987
+ return headline(text, 1);
988
+ }
989
+ function h2(text) {
990
+ return headline(text, 2);
991
+ }
992
+ function h3(text) {
993
+ return headline(text, 3);
994
+ }
995
+ function h4(text) {
996
+ return headline(text, 4);
997
+ }
998
+ function h5(text) {
999
+ return headline(text, 5);
1000
+ }
1001
+ function h6(text) {
1002
+ return headline(text, 6);
1003
+ }
1004
+
1005
+ // packages/utils/src/lib/text-formats/md/image.ts
1006
+ function image(src, alt) {
1007
+ return `![${alt}](${src})`;
1008
+ }
1009
+
1010
+ // packages/utils/src/lib/text-formats/md/link.ts
1011
+ function link2(href, text) {
1012
+ return `[${text || href}](${href})`;
1013
+ }
1014
+
1015
+ // packages/utils/src/lib/text-formats/md/list.ts
1016
+ function li(text, order = "unordered") {
1017
+ const style = order === "unordered" ? "-" : "- [ ]";
1018
+ return `${style} ${text}`;
1019
+ }
1020
+ function indentation(text, level = 1) {
1021
+ return `${TAB.repeat(level)}${text}`;
1022
+ }
1023
+
1024
+ // packages/utils/src/lib/text-formats/md/paragraphs.ts
1025
+ function paragraphs(...sections) {
1026
+ return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
1027
+ }
1028
+
1029
+ // packages/utils/src/lib/text-formats/md/section.ts
1030
+ function section(...contents) {
1031
+ return `${lines(...contents)}${NEW_LINE}`;
1032
+ }
1033
+ function lines(...contents) {
1034
+ return `${contents.filter(Boolean).join(NEW_LINE)}`;
1035
+ }
1036
+
1037
+ // packages/utils/src/lib/text-formats/md/table.ts
1038
+ var alignString = /* @__PURE__ */ new Map([
1039
+ ["left", ":--"],
1040
+ ["center", ":--:"],
1041
+ ["right", "--:"]
1042
+ ]);
1043
+ function tableRow(rows) {
1044
+ return `|${rows.join("|")}|`;
1045
+ }
1046
+ function table2(data) {
1047
+ if (data.rows.length === 0) {
1048
+ throw new Error("Data can't be empty");
1049
+ }
1050
+ const alignmentRow = getColumnAlignments(data).map(
1051
+ (s) => alignString.get(s) ?? String(alignString.get("center"))
1052
+ );
1053
+ return section(
1054
+ `${lines(
1055
+ tableRow(columnsToStringArray(data)),
1056
+ tableRow(alignmentRow),
1057
+ ...rowToStringArray(data).map(tableRow)
1058
+ )}`
1059
+ );
1060
+ }
1061
+
1062
+ // packages/utils/src/lib/text-formats/index.ts
1063
+ var md = {
1064
+ bold: bold2,
1065
+ italic: italic2,
1066
+ strikeThrough,
1067
+ code: code2,
1068
+ link: link2,
1069
+ image,
1070
+ headline,
1071
+ h,
1072
+ h1,
1073
+ h2,
1074
+ h3,
1075
+ h4,
1076
+ h5,
1077
+ h6,
1078
+ indentation,
1079
+ lines,
1080
+ li,
1081
+ section,
1082
+ paragraphs,
1083
+ table: table2
1084
+ };
1085
+ var html = {
1086
+ bold,
1087
+ italic,
1088
+ code,
1089
+ link,
1090
+ details,
1091
+ table
1092
+ };
1093
+
761
1094
  // packages/utils/src/lib/file-system.ts
762
1095
  import { bundleRequire } from "bundle-require";
763
1096
  import chalk2 from "chalk";
@@ -812,26 +1145,45 @@ function pluginWorkDir(slug) {
812
1145
  return join("node_modules", ".code-pushup", slug);
813
1146
  }
814
1147
 
815
- // packages/utils/src/lib/git.ts
1148
+ // packages/utils/src/lib/reports/utils.ts
1149
+ var { image: image2, bold: boldMd } = md;
1150
+
1151
+ // packages/utils/src/lib/git/git.ts
816
1152
  import { simpleGit } from "simple-git";
817
1153
 
818
- // packages/utils/src/lib/transform.ts
819
- import { platform } from "node:os";
820
- function objectToEntries(obj) {
821
- return Object.entries(obj);
822
- }
823
- function toUnixNewlines(text) {
824
- return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
825
- }
826
- function fromJsonLines(jsonLines) {
827
- const unifiedNewLines = toUnixNewlines(jsonLines).trim();
828
- return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
829
- }
1154
+ // packages/utils/src/lib/git/git.commits-and-tags.ts
1155
+ import { simpleGit as simpleGit2 } from "simple-git";
1156
+
1157
+ // packages/utils/src/lib/semver.ts
1158
+ import { rcompare, valid } from "semver";
830
1159
 
831
1160
  // packages/utils/src/lib/progress.ts
832
1161
  import chalk3 from "chalk";
833
1162
  import { MultiProgressBars } from "multi-progress-bars";
834
1163
 
1164
+ // packages/utils/src/lib/reports/formatting.ts
1165
+ var { headline: headline2, lines: lines2, link: link3, section: section2, table: table3 } = md;
1166
+
1167
+ // packages/utils/src/lib/reports/generate-md-report-categoy-section.ts
1168
+ var { link: link4, section: section3, h2: h22, lines: lines3, li: li2, bold: boldMd2, h3: h32, indentation: indentation2 } = md;
1169
+
1170
+ // packages/utils/src/lib/reports/generate-md-report.ts
1171
+ var { h1: h12, h2: h23, h3: h33, lines: lines4, link: link5, section: section4, code: codeMd } = md;
1172
+ var { bold: boldHtml, details: details2 } = html;
1173
+
1174
+ // packages/utils/src/lib/reports/generate-md-reports-diff.ts
1175
+ var {
1176
+ h1: h13,
1177
+ h2: h24,
1178
+ lines: lines5,
1179
+ link: link6,
1180
+ bold: boldMd3,
1181
+ italic: italicMd,
1182
+ table: table4,
1183
+ section: section5
1184
+ } = md;
1185
+ var { details: details3 } = html;
1186
+
835
1187
  // packages/utils/src/lib/reports/log-stdout-summary.ts
836
1188
  import chalk4 from "chalk";
837
1189
 
@@ -1092,17 +1444,73 @@ function validateYarnv1Result(result) {
1092
1444
  return [vulnerabilities, summary];
1093
1445
  }
1094
1446
 
1447
+ // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/constants.ts
1448
+ var outdatedtoFieldMapper = {
1449
+ name: "Package",
1450
+ current: "Current",
1451
+ latest: "Latest",
1452
+ type: "Package Type",
1453
+ url: "URL"
1454
+ };
1455
+ var REQUIRED_OUTDATED_FIELDS = [
1456
+ "Package",
1457
+ "Current",
1458
+ "Latest",
1459
+ "Package Type"
1460
+ ];
1461
+
1462
+ // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/types.ts
1463
+ var yarnv1FieldNames = [
1464
+ "Package",
1465
+ "Current",
1466
+ "Latest",
1467
+ "Package Type",
1468
+ "URL"
1469
+ ];
1470
+
1095
1471
  // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/outdated-result.ts
1096
1472
  function yarnv1ToOutdatedResult(output) {
1097
1473
  const yarnv1Outdated = fromJsonLines(output);
1474
+ const fields = yarnv1Outdated[1].data.head;
1098
1475
  const dependencies = yarnv1Outdated[1].data.body;
1099
- return dependencies.map(([name2, current, _, latest, __, type, url]) => ({
1100
- name: name2,
1101
- current,
1102
- latest,
1103
- type,
1104
- url
1105
- }));
1476
+ if (dependencies.length === 0) {
1477
+ return [];
1478
+ }
1479
+ validateOutdatedFields(fields);
1480
+ const indexMapping = getOutdatedFieldIndexes(fields);
1481
+ return dependencies.map(
1482
+ (dep) => objectFromEntries(
1483
+ objectToKeys(indexMapping).map((field) => [field, dep[indexMapping[field]]]).filter(
1484
+ (entry) => entry[1] != null
1485
+ )
1486
+ )
1487
+ );
1488
+ }
1489
+ function validateOutdatedFields(head) {
1490
+ const relevantFields = head.filter(isYarnv1FieldName);
1491
+ if (hasAllRequiredFields(relevantFields)) {
1492
+ return true;
1493
+ }
1494
+ throw new Error(
1495
+ `Yarn v1 outdated: Template [${head.join(
1496
+ ", "
1497
+ )}] does not contain all required fields [${yarnv1FieldNames.join(", ")}]`
1498
+ );
1499
+ }
1500
+ function isYarnv1FieldName(value) {
1501
+ const names = yarnv1FieldNames;
1502
+ return names.includes(value);
1503
+ }
1504
+ function hasAllRequiredFields(head) {
1505
+ return REQUIRED_OUTDATED_FIELDS.every((field) => head.includes(field));
1506
+ }
1507
+ function getOutdatedFieldIndexes(all) {
1508
+ return objectFromEntries(
1509
+ objectToEntries(outdatedtoFieldMapper).map(([outdatedField, yarnField]) => [
1510
+ outdatedField,
1511
+ all.indexOf(yarnField)
1512
+ ])
1513
+ );
1106
1514
  }
1107
1515
 
1108
1516
  // packages/plugin-js-packages/src/lib/package-managers/yarn-classic/yarn-classic.ts
@@ -1231,6 +1639,21 @@ var PLUGIN_CONFIG_PATH = join2(
1231
1639
  "plugin-config.json"
1232
1640
  );
1233
1641
 
1642
+ // packages/plugin-js-packages/src/lib/runner/outdated/transform.ts
1643
+ import { clean, diff, neq } from "semver";
1644
+
1645
+ // packages/plugin-js-packages/src/lib/runner/outdated/constants.ts
1646
+ var outdatedSeverity = {
1647
+ major: "error",
1648
+ premajor: "info",
1649
+ minor: "warning",
1650
+ preminor: "info",
1651
+ patch: "info",
1652
+ prepatch: "info",
1653
+ prerelease: "info"
1654
+ };
1655
+ var RELEASE_TYPES = objectToKeys(outdatedSeverity);
1656
+
1234
1657
  // packages/plugin-js-packages/src/lib/runner/index.ts
1235
1658
  async function createRunnerConfig(scriptPath, config) {
1236
1659
  await ensureDirectoryExists(dirname(PLUGIN_CONFIG_PATH));