@code-pushup/js-packages-plugin 0.45.0 → 0.46.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/README.md CHANGED
@@ -113,7 +113,7 @@ The plugin accepts the following parameters:
113
113
  - `packageManager`: The package manager you are using. Supported values: `npm`, `yarn-classic` (v1), `yarn-modern` (v2+), `pnpm`.
114
114
  - (optional) `checks`: Array of checks to be run. Supported commands: `audit`, `outdated`. Both are configured by default.
115
115
  - (optional) `dependencyGroups`: Array of dependency groups to be checked. `prod` and `dev` are configured by default. `optional` are opt-in.
116
- - (optional) `packageJsonPath`: File path to `package.json`. Defaults to current folder. Multiple `package.json` files are currently not supported.
116
+ - (optional) `packageJsonPaths`: File path(s) to `package.json`. Root `package.json` is used by default. Multiple `package.json` paths may be passed. If `{ autoSearch: true }` is provided, all `package.json` files in the repository are searched.
117
117
  - (optional) `auditLevelMapping`: If you wish to set a custom level of issue severity based on audit vulnerability level, you may do so here. Any omitted values will be filled in by defaults. Audit levels are: `critical`, `high`, `moderate`, `low` and `info`. Issue severities are: `error`, `warn` and `info`. By default the mapping is as follows: `critical` and `high` → `error`; `moderate` and `low` → `warning`; `info` → `info`.
118
118
 
119
119
  ### Audits and group
package/bin.js CHANGED
@@ -2,300 +2,6 @@
2
2
  import { writeFile } from "node:fs/promises";
3
3
  import { dirname } from "node:path";
4
4
 
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
- };
298
-
299
5
  // packages/models/src/lib/implementation/schemas.ts
300
6
  import { MATERIAL_ICONS } from "vscode-material-icons";
301
7
  import { z } from "zod";
@@ -405,6 +111,7 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
405
111
  }).min(1, { message: "file name is invalid" });
406
112
  var positiveIntSchema = z.number().int().positive();
407
113
  var nonnegativeIntSchema = z.number().int().nonnegative();
114
+ var nonnegativeNumberSchema = z.number().nonnegative();
408
115
  function packageVersionSchema(options) {
409
116
  const { versionDescription = "NPM version of the package", required } = options ?? {};
410
117
  const packageSchema = z.string({ description: "NPM package name" });
@@ -417,7 +124,7 @@ function packageVersionSchema(options) {
417
124
  { description: "NPM package name and version of a published package" }
418
125
  );
419
126
  }
420
- var weightSchema = nonnegativeIntSchema.describe(
127
+ var weightSchema = nonnegativeNumberSchema.describe(
421
128
  "Coefficient for the given score (use weight 0 if only for display)"
422
129
  );
423
130
  function weightedRefSchema(description, slugDescription) {
@@ -559,7 +266,7 @@ var tableObjectSchema = tableSharedSchema.merge(
559
266
  var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
560
267
 
561
268
  // packages/models/src/lib/audit-output.ts
562
- var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
269
+ var auditValueSchema = nonnegativeNumberSchema.describe("Raw numeric value");
563
270
  var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
564
271
  var auditDetailsSchema = z5.object(
565
272
  {
@@ -1004,79 +711,394 @@ function pluralize(text, amount) {
1004
711
  if (amount != null && Math.abs(amount) === 1) {
1005
712
  return text;
1006
713
  }
1007
- if (text.endsWith("y")) {
1008
- return `${text.slice(0, -1)}ies`;
714
+ if (text.endsWith("y")) {
715
+ return `${text.slice(0, -1)}ies`;
716
+ }
717
+ if (text.endsWith("s")) {
718
+ return `${text}es`;
719
+ }
720
+ return `${text}s`;
721
+ }
722
+
723
+ // packages/utils/src/lib/guards.ts
724
+ function isPromiseFulfilledResult(result) {
725
+ return result.status === "fulfilled";
726
+ }
727
+ function isPromiseRejectedResult(result) {
728
+ return result.status === "rejected";
729
+ }
730
+
731
+ // packages/utils/src/lib/logging.ts
732
+ import isaacs_cliui from "@isaacs/cliui";
733
+ import { cliui } from "@poppinss/cliui";
734
+ import chalk from "chalk";
735
+
736
+ // packages/utils/src/lib/reports/constants.ts
737
+ var TERMINAL_WIDTH = 80;
738
+
739
+ // packages/utils/src/lib/logging.ts
740
+ var singletonUiInstance;
741
+ function ui() {
742
+ if (singletonUiInstance === void 0) {
743
+ singletonUiInstance = cliui();
744
+ }
745
+ return {
746
+ ...singletonUiInstance,
747
+ row: (args) => {
748
+ logListItem(args);
749
+ }
750
+ };
751
+ }
752
+ var singletonisaacUi;
753
+ function logListItem(args) {
754
+ if (singletonisaacUi === void 0) {
755
+ singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
756
+ }
757
+ singletonisaacUi.div(...args);
758
+ const content = singletonisaacUi.toString();
759
+ singletonisaacUi.rows = [];
760
+ singletonUiInstance?.logger.log(content);
761
+ }
762
+
763
+ // packages/utils/src/lib/file-system.ts
764
+ async function readTextFile(path) {
765
+ const buffer = await readFile(path);
766
+ return buffer.toString();
767
+ }
768
+ async function readJsonFile(path) {
769
+ const text = await readTextFile(path);
770
+ return JSON.parse(text);
771
+ }
772
+ async function ensureDirectoryExists(baseDir) {
773
+ try {
774
+ await mkdir(baseDir, { recursive: true });
775
+ return;
776
+ } catch (error) {
777
+ ui().logger.info(error.message);
778
+ if (error.code !== "EEXIST") {
779
+ throw error;
780
+ }
781
+ }
782
+ }
783
+ function pluginWorkDir(slug) {
784
+ return join("node_modules", ".code-pushup", slug);
785
+ }
786
+ async function crawlFileSystem(options) {
787
+ const {
788
+ directory,
789
+ pattern,
790
+ fileTransform = (filePath) => filePath
791
+ } = options;
792
+ const files = await readdir(directory);
793
+ const promises = files.map(async (file) => {
794
+ const filePath = join(directory, file);
795
+ const stats = await stat(filePath);
796
+ if (stats.isDirectory()) {
797
+ return crawlFileSystem({ directory: filePath, pattern, fileTransform });
798
+ }
799
+ if (stats.isFile() && (!pattern || new RegExp(pattern).test(file))) {
800
+ return fileTransform(filePath);
801
+ }
802
+ return [];
803
+ });
804
+ const resultsNestedArray = await Promise.all(promises);
805
+ return resultsNestedArray.flat();
806
+ }
807
+
808
+ // packages/utils/src/lib/text-formats/constants.ts
809
+ var NEW_LINE = "\n";
810
+ var TAB = " ";
811
+
812
+ // packages/utils/src/lib/text-formats/html/details.ts
813
+ function details(title, content, cfg = { open: false }) {
814
+ 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.
815
+ NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
816
+ // ⚠️ The blank line ensure Markdown in content is rendered correctly.
817
+ NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
818
+ NEW_LINE}`;
819
+ }
820
+
821
+ // packages/utils/src/lib/text-formats/html/font-style.ts
822
+ var boldElement = "b";
823
+ function bold(text) {
824
+ return `<${boldElement}>${text}</${boldElement}>`;
825
+ }
826
+ var italicElement = "i";
827
+ function italic(text) {
828
+ return `<${italicElement}>${text}</${italicElement}>`;
829
+ }
830
+ var codeElement = "code";
831
+ function code(text) {
832
+ return `<${codeElement}>${text}</${codeElement}>`;
833
+ }
834
+
835
+ // packages/utils/src/lib/text-formats/html/link.ts
836
+ function link(href, text) {
837
+ return `<a href="${href}">${text || href}"</a>`;
838
+ }
839
+
840
+ // packages/utils/src/lib/transform.ts
841
+ import { platform } from "node:os";
842
+ function objectToKeys(obj) {
843
+ return Object.keys(obj);
844
+ }
845
+ function objectToEntries(obj) {
846
+ return Object.entries(obj);
847
+ }
848
+ function objectFromEntries(entries) {
849
+ return Object.fromEntries(entries);
850
+ }
851
+ function toUnixNewlines(text) {
852
+ return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
853
+ }
854
+ function fromJsonLines(jsonLines) {
855
+ const unifiedNewLines = toUnixNewlines(jsonLines).trim();
856
+ return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
857
+ }
858
+ function capitalize(text) {
859
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
860
+ 1
861
+ )}`;
862
+ }
863
+ function apostrophize(text, upperCase) {
864
+ const lastCharMatch = text.match(/(\w)\W*$/);
865
+ const lastChar = lastCharMatch?.[1] ?? "";
866
+ return `${text}'${lastChar.toLocaleLowerCase() === "s" ? "" : upperCase ? "S" : "s"}`;
867
+ }
868
+
869
+ // packages/utils/src/lib/table.ts
870
+ function rowToStringArray({ rows, columns = [] }) {
871
+ if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
872
+ throw new TypeError(
873
+ "Column can`t be object when rows are primitive values"
874
+ );
875
+ }
876
+ return rows.map((row) => {
877
+ if (Array.isArray(row)) {
878
+ return row.map(String);
879
+ }
880
+ const objectRow = row;
881
+ if (columns.length === 0 || typeof columns.at(0) === "string") {
882
+ return Object.values(objectRow).map(String);
883
+ }
884
+ return columns.map(
885
+ ({ key }) => String(objectRow[key])
886
+ );
887
+ });
888
+ }
889
+ function columnsToStringArray({ rows, columns = [] }) {
890
+ const firstRow = rows.at(0);
891
+ const primitiveRows = Array.isArray(firstRow);
892
+ if (typeof columns.at(0) === "string" && !primitiveRows) {
893
+ throw new Error("invalid union type. Caught by model parsing.");
894
+ }
895
+ if (columns.length === 0) {
896
+ if (Array.isArray(firstRow)) {
897
+ return firstRow.map((_, idx) => String(idx));
898
+ }
899
+ return Object.keys(firstRow);
900
+ }
901
+ if (typeof columns.at(0) === "string") {
902
+ return columns.map(String);
1009
903
  }
1010
- if (text.endsWith("s")) {
1011
- return `${text}es`;
904
+ const cols = columns;
905
+ return cols.map(({ label, key }) => label ?? capitalize(key));
906
+ }
907
+ function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
908
+ const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
909
+ if (typeof column === "string") {
910
+ return column;
911
+ } else if (typeof column === "object") {
912
+ return column.align ?? "center";
913
+ } else {
914
+ return "center";
1012
915
  }
1013
- return `${text}s`;
916
+ }
917
+ function getColumnAlignmentForIndex(targetIdx, columns = []) {
918
+ const column = columns.at(targetIdx);
919
+ if (column == null) {
920
+ return "center";
921
+ } else if (typeof column === "string") {
922
+ return column;
923
+ } else if (typeof column === "object") {
924
+ return column.align ?? "center";
925
+ } else {
926
+ return "center";
927
+ }
928
+ }
929
+ function getColumnAlignments({
930
+ rows,
931
+ columns = []
932
+ }) {
933
+ if (rows.at(0) == null) {
934
+ throw new Error("first row can`t be undefined.");
935
+ }
936
+ if (Array.isArray(rows.at(0))) {
937
+ const firstPrimitiveRow = rows.at(0);
938
+ return Array.from({ length: firstPrimitiveRow.length }).map(
939
+ (_, idx) => getColumnAlignmentForIndex(idx, columns)
940
+ );
941
+ }
942
+ const firstObject = rows.at(0);
943
+ return Object.keys(firstObject).map(
944
+ (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
945
+ );
1014
946
  }
1015
947
 
1016
- // packages/utils/src/lib/guards.ts
1017
- function isPromiseFulfilledResult(result) {
1018
- return result.status === "fulfilled";
948
+ // packages/utils/src/lib/text-formats/html/table.ts
949
+ function wrap(elem, content) {
950
+ return `<${elem}>${content}</${elem}>${NEW_LINE}`;
1019
951
  }
1020
- function isPromiseRejectedResult(result) {
1021
- return result.status === "rejected";
952
+ function wrapRow(content) {
953
+ const elem = "tr";
954
+ return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
955
+ }
956
+ function table(tableData) {
957
+ if (tableData.rows.length === 0) {
958
+ throw new Error("Data can't be empty");
959
+ }
960
+ const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
961
+ const tableHeaderRow = wrapRow(tableHeaderCols);
962
+ const tableBody = rowToStringArray(tableData).map((arr) => {
963
+ const columns = arr.map((s) => wrap("td", s)).join("");
964
+ return wrapRow(columns);
965
+ }).join("");
966
+ return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
1022
967
  }
1023
968
 
1024
- // packages/utils/src/lib/logging.ts
1025
- import isaacs_cliui from "@isaacs/cliui";
1026
- import { cliui } from "@poppinss/cliui";
1027
- import chalk from "chalk";
969
+ // packages/utils/src/lib/text-formats/md/font-style.ts
970
+ var boldWrap = "**";
971
+ function bold2(text) {
972
+ return `${boldWrap}${text}${boldWrap}`;
973
+ }
974
+ var italicWrap = "_";
975
+ function italic2(text) {
976
+ return `${italicWrap}${text}${italicWrap}`;
977
+ }
978
+ var strikeThroughWrap = "~";
979
+ function strikeThrough(text) {
980
+ return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
981
+ }
982
+ var codeWrap = "`";
983
+ function code2(text) {
984
+ return `${codeWrap}${text}${codeWrap}`;
985
+ }
1028
986
 
1029
- // packages/utils/src/lib/reports/constants.ts
1030
- var TERMINAL_WIDTH = 80;
987
+ // packages/utils/src/lib/text-formats/md/headline.ts
988
+ function headline(text, hierarchy = 1) {
989
+ return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
990
+ }
991
+ function h(text, hierarchy = 1) {
992
+ return headline(text, hierarchy);
993
+ }
994
+ function h1(text) {
995
+ return headline(text, 1);
996
+ }
997
+ function h2(text) {
998
+ return headline(text, 2);
999
+ }
1000
+ function h3(text) {
1001
+ return headline(text, 3);
1002
+ }
1003
+ function h4(text) {
1004
+ return headline(text, 4);
1005
+ }
1006
+ function h5(text) {
1007
+ return headline(text, 5);
1008
+ }
1009
+ function h6(text) {
1010
+ return headline(text, 6);
1011
+ }
1031
1012
 
1032
- // packages/utils/src/lib/logging.ts
1033
- var singletonUiInstance;
1034
- function ui() {
1035
- if (singletonUiInstance === void 0) {
1036
- singletonUiInstance = cliui();
1037
- }
1038
- return {
1039
- ...singletonUiInstance,
1040
- row: (args) => {
1041
- logListItem(args);
1042
- }
1043
- };
1013
+ // packages/utils/src/lib/text-formats/md/image.ts
1014
+ function image(src, alt) {
1015
+ return `![${alt}](${src})`;
1044
1016
  }
1045
- var singletonisaacUi;
1046
- function logListItem(args) {
1047
- if (singletonisaacUi === void 0) {
1048
- singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
1049
- }
1050
- singletonisaacUi.div(...args);
1051
- const content = singletonisaacUi.toString();
1052
- singletonisaacUi.rows = [];
1053
- singletonUiInstance?.logger.log(content);
1017
+
1018
+ // packages/utils/src/lib/text-formats/md/link.ts
1019
+ function link2(href, text) {
1020
+ return `[${text || href}](${href})`;
1054
1021
  }
1055
1022
 
1056
- // packages/utils/src/lib/file-system.ts
1057
- async function readTextFile(path) {
1058
- const buffer = await readFile(path);
1059
- return buffer.toString();
1023
+ // packages/utils/src/lib/text-formats/md/list.ts
1024
+ function li(text, order = "unordered") {
1025
+ const style = order === "unordered" ? "-" : "- [ ]";
1026
+ return `${style} ${text}`;
1060
1027
  }
1061
- async function readJsonFile(path) {
1062
- const text = await readTextFile(path);
1063
- return JSON.parse(text);
1028
+ function indentation(text, level = 1) {
1029
+ return `${TAB.repeat(level)}${text}`;
1064
1030
  }
1065
- async function ensureDirectoryExists(baseDir) {
1066
- try {
1067
- await mkdir(baseDir, { recursive: true });
1068
- return;
1069
- } catch (error) {
1070
- ui().logger.info(error.message);
1071
- if (error.code !== "EEXIST") {
1072
- throw error;
1073
- }
1074
- }
1031
+
1032
+ // packages/utils/src/lib/text-formats/md/paragraphs.ts
1033
+ function paragraphs(...sections) {
1034
+ return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
1075
1035
  }
1076
- function pluginWorkDir(slug) {
1077
- return join("node_modules", ".code-pushup", slug);
1036
+
1037
+ // packages/utils/src/lib/text-formats/md/section.ts
1038
+ function section(...contents) {
1039
+ return `${lines(...contents)}${NEW_LINE}`;
1040
+ }
1041
+ function lines(...contents) {
1042
+ return `${contents.filter(Boolean).join(NEW_LINE)}`;
1043
+ }
1044
+
1045
+ // packages/utils/src/lib/text-formats/md/table.ts
1046
+ var alignString = /* @__PURE__ */ new Map([
1047
+ ["left", ":--"],
1048
+ ["center", ":--:"],
1049
+ ["right", "--:"]
1050
+ ]);
1051
+ function tableRow(rows) {
1052
+ return `|${rows.join("|")}|`;
1053
+ }
1054
+ function table2(data) {
1055
+ if (data.rows.length === 0) {
1056
+ throw new Error("Data can't be empty");
1057
+ }
1058
+ const alignmentRow = getColumnAlignments(data).map(
1059
+ (s) => alignString.get(s) ?? String(alignString.get("center"))
1060
+ );
1061
+ return section(
1062
+ `${lines(
1063
+ tableRow(columnsToStringArray(data)),
1064
+ tableRow(alignmentRow),
1065
+ ...rowToStringArray(data).map(tableRow)
1066
+ )}`
1067
+ );
1078
1068
  }
1079
1069
 
1070
+ // packages/utils/src/lib/text-formats/index.ts
1071
+ var md = {
1072
+ bold: bold2,
1073
+ italic: italic2,
1074
+ strikeThrough,
1075
+ code: code2,
1076
+ link: link2,
1077
+ image,
1078
+ headline,
1079
+ h,
1080
+ h1,
1081
+ h2,
1082
+ h3,
1083
+ h4,
1084
+ h5,
1085
+ h6,
1086
+ indentation,
1087
+ lines,
1088
+ li,
1089
+ section,
1090
+ paragraphs,
1091
+ table: table2
1092
+ };
1093
+ var html = {
1094
+ bold,
1095
+ italic,
1096
+ code,
1097
+ link,
1098
+ details,
1099
+ table
1100
+ };
1101
+
1080
1102
  // packages/utils/src/lib/reports/utils.ts
1081
1103
  var { image: image2, bold: boldMd } = md;
1082
1104
  function calcDuration(start, stop) {
@@ -1194,6 +1216,12 @@ var packageManagerIdSchema = z16.enum([
1194
1216
  "yarn-modern",
1195
1217
  "pnpm"
1196
1218
  ]);
1219
+ var packageJsonPathSchema = z16.union([
1220
+ z16.array(z16.string()).min(1),
1221
+ z16.object({ autoSearch: z16.literal(true) })
1222
+ ]).describe(
1223
+ "File paths to package.json. Looks only at root package.json by default"
1224
+ ).default(["package.json"]);
1197
1225
  var packageAuditLevels = [
1198
1226
  "critical",
1199
1227
  "high",
@@ -1222,9 +1250,19 @@ var jsPackagesPluginConfigSchema = z16.object({
1222
1250
  auditLevelMapping: z16.record(packageAuditLevelSchema, issueSeveritySchema, {
1223
1251
  description: "Mapping of audit levels to issue severity. Custom mapping or overrides may be entered manually, otherwise has a default preset."
1224
1252
  }).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping),
1225
- packageJsonPath: z16.string().describe("File path to package.json. Defaults to current folder.").default("package.json")
1253
+ packageJsonPaths: packageJsonPathSchema
1226
1254
  });
1227
1255
 
1256
+ // packages/plugin-js-packages/src/lib/runner/utils.ts
1257
+ import { sep } from "node:path";
1258
+
1259
+ // packages/plugin-js-packages/src/lib/runner/outdated/types.ts
1260
+ var dependencyGroupLong = [
1261
+ "dependencies",
1262
+ "devDependencies",
1263
+ "optionalDependencies"
1264
+ ];
1265
+
1228
1266
  // packages/plugin-js-packages/src/lib/runner/utils.ts
1229
1267
  function filterAuditResult(result, key, referenceResult) {
1230
1268
  if (result.vulnerabilities.length === 0) {
@@ -1256,13 +1294,35 @@ function filterAuditResult(result, key, referenceResult) {
1256
1294
  summary: uniqueResult.summary
1257
1295
  };
1258
1296
  }
1259
- async function getTotalDependencies(packageJsonPath) {
1260
- const packageJson = await readJsonFile(packageJsonPath);
1297
+ async function findAllPackageJson() {
1298
+ return (await crawlFileSystem({
1299
+ directory: ".",
1300
+ pattern: /(^|[\\/])package\.json$/
1301
+ })).filter(
1302
+ (path) => !path.startsWith(`node_modules${sep}`) && !path.includes(`${sep}node_modules${sep}`) && !path.startsWith(`.nx${sep}`)
1303
+ );
1304
+ }
1305
+ async function getTotalDependencies(packageJsonPaths) {
1306
+ const parsedDeps = await Promise.all(
1307
+ packageJsonPaths.map(readJsonFile)
1308
+ );
1309
+ const mergedDeps = parsedDeps.reduce(
1310
+ (acc, depMapper) => objectFromEntries(
1311
+ dependencyGroupLong.map((group) => {
1312
+ const deps = depMapper[group];
1313
+ return [
1314
+ group,
1315
+ [...acc[group], ...deps == null ? [] : objectToKeys(deps)]
1316
+ ];
1317
+ })
1318
+ ),
1319
+ { dependencies: [], devDependencies: [], optionalDependencies: [] }
1320
+ );
1261
1321
  return objectFromEntries(
1262
- dependencyGroups.map((depGroup) => {
1263
- const deps = packageJson[dependencyGroupToLong[depGroup]];
1264
- return [depGroup, deps == null ? 0 : objectToKeys(deps).length];
1265
- })
1322
+ objectToKeys(mergedDeps).map((deps) => [
1323
+ deps,
1324
+ new Set(mergedDeps[deps]).size
1325
+ ])
1266
1326
  );
1267
1327
  }
1268
1328
 
@@ -1872,32 +1932,36 @@ async function executeRunner() {
1872
1932
  packageManager,
1873
1933
  checks,
1874
1934
  auditLevelMapping,
1875
- packageJsonPath,
1935
+ packageJsonPaths,
1876
1936
  dependencyGroups: depGroups
1877
1937
  } = await readJsonFile(PLUGIN_CONFIG_PATH);
1878
1938
  const auditResults = checks.includes("audit") ? await processAudit(packageManager, depGroups, auditLevelMapping) : [];
1879
- const outdatedResults = checks.includes("outdated") ? await processOutdated(packageManager, depGroups, packageJsonPath) : [];
1939
+ const outdatedResults = checks.includes("outdated") ? await processOutdated(packageManager, depGroups, packageJsonPaths) : [];
1880
1940
  const checkResults = [...auditResults, ...outdatedResults];
1881
1941
  await ensureDirectoryExists(dirname(RUNNER_OUTPUT_PATH));
1882
1942
  await writeFile(RUNNER_OUTPUT_PATH, JSON.stringify(checkResults));
1883
1943
  }
1884
- async function processOutdated(id, depGroups, packageJsonPath) {
1944
+ async function processOutdated(id, depGroups, packageJsonPaths) {
1885
1945
  const pm = packageManagers[id];
1886
- const { stdout } = await executeProcess({
1946
+ const { stdout, stderr } = await executeProcess({
1887
1947
  command: pm.command,
1888
1948
  args: pm.outdated.commandArgs,
1889
1949
  cwd: process.cwd(),
1890
1950
  ignoreExitCode: true
1891
1951
  // outdated returns exit code 1 when outdated dependencies are found
1892
1952
  });
1893
- const depTotals = await getTotalDependencies(packageJsonPath);
1953
+ if (stderr) {
1954
+ throw new Error(`JS packages plugin: outdated error: ${stderr}`);
1955
+ }
1956
+ const finalPaths = Array.isArray(packageJsonPaths) ? packageJsonPaths : await findAllPackageJson();
1957
+ const depTotals = await getTotalDependencies(finalPaths);
1894
1958
  const normalizedResult = pm.outdated.unifyResult(stdout);
1895
1959
  return depGroups.map(
1896
1960
  (depGroup) => outdatedResultToAuditOutput(
1897
1961
  normalizedResult,
1898
1962
  id,
1899
1963
  depGroup,
1900
- depTotals[depGroup]
1964
+ depTotals[dependencyGroupToLong[depGroup]]
1901
1965
  )
1902
1966
  );
1903
1967
  }
@@ -1910,12 +1974,15 @@ async function processAudit(id, depGroups, auditLevelMapping) {
1910
1974
  const auditResults = await Promise.allSettled(
1911
1975
  compatibleAuditDepGroups.map(
1912
1976
  async (depGroup) => {
1913
- const { stdout } = await executeProcess({
1977
+ const { stdout, stderr } = await executeProcess({
1914
1978
  command: pm.command,
1915
1979
  args: pm.audit.getCommandArgs(depGroup),
1916
1980
  cwd: process.cwd(),
1917
1981
  ignoreExitCode: pm.audit.ignoreExitCode
1918
1982
  });
1983
+ if (stderr) {
1984
+ throw new Error(`JS packages plugin: audit error: ${stderr}`);
1985
+ }
1919
1986
  return [depGroup, pm.audit.unifyResult(stdout)];
1920
1987
  }
1921
1988
  )
package/index.js CHANGED
@@ -4,7 +4,7 @@ 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.45.0";
7
+ var version = "0.46.0";
8
8
 
9
9
  // packages/plugin-js-packages/src/lib/config.ts
10
10
  import { z as z16 } from "zod";
@@ -118,6 +118,7 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
118
118
  }).min(1, { message: "file name is invalid" });
119
119
  var positiveIntSchema = z.number().int().positive();
120
120
  var nonnegativeIntSchema = z.number().int().nonnegative();
121
+ var nonnegativeNumberSchema = z.number().nonnegative();
121
122
  function packageVersionSchema(options) {
122
123
  const { versionDescription = "NPM version of the package", required } = options ?? {};
123
124
  const packageSchema = z.string({ description: "NPM package name" });
@@ -130,7 +131,7 @@ function packageVersionSchema(options) {
130
131
  { description: "NPM package name and version of a published package" }
131
132
  );
132
133
  }
133
- var weightSchema = nonnegativeIntSchema.describe(
134
+ var weightSchema = nonnegativeNumberSchema.describe(
134
135
  "Coefficient for the given score (use weight 0 if only for display)"
135
136
  );
136
137
  function weightedRefSchema(description, slugDescription) {
@@ -272,7 +273,7 @@ var tableObjectSchema = tableSharedSchema.merge(
272
273
  var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
273
274
 
274
275
  // packages/models/src/lib/audit-output.ts
275
- var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
276
+ var auditValueSchema = nonnegativeNumberSchema.describe("Raw numeric value");
276
277
  var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
277
278
  var auditDetailsSchema = z5.object(
278
279
  {
@@ -737,6 +738,12 @@ var packageManagerIdSchema = z16.enum([
737
738
  "yarn-modern",
738
739
  "pnpm"
739
740
  ]);
741
+ var packageJsonPathSchema = z16.union([
742
+ z16.array(z16.string()).min(1),
743
+ z16.object({ autoSearch: z16.literal(true) })
744
+ ]).describe(
745
+ "File paths to package.json. Looks only at root package.json by default"
746
+ ).default(["package.json"]);
740
747
  var packageAuditLevels = [
741
748
  "critical",
742
749
  "high",
@@ -765,9 +772,66 @@ var jsPackagesPluginConfigSchema = z16.object({
765
772
  auditLevelMapping: z16.record(packageAuditLevelSchema, issueSeveritySchema, {
766
773
  description: "Mapping of audit levels to issue severity. Custom mapping or overrides may be entered manually, otherwise has a default preset."
767
774
  }).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping),
768
- packageJsonPath: z16.string().describe("File path to package.json. Defaults to current folder.").default("package.json")
775
+ packageJsonPaths: packageJsonPathSchema
769
776
  });
770
777
 
778
+ // packages/utils/src/lib/file-system.ts
779
+ import { bundleRequire } from "bundle-require";
780
+ import chalk2 from "chalk";
781
+ import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
782
+ import { join } from "node:path";
783
+
784
+ // packages/utils/src/lib/logging.ts
785
+ import isaacs_cliui from "@isaacs/cliui";
786
+ import { cliui } from "@poppinss/cliui";
787
+ import chalk from "chalk";
788
+
789
+ // packages/utils/src/lib/reports/constants.ts
790
+ var TERMINAL_WIDTH = 80;
791
+
792
+ // packages/utils/src/lib/logging.ts
793
+ var singletonUiInstance;
794
+ function ui() {
795
+ if (singletonUiInstance === void 0) {
796
+ singletonUiInstance = cliui();
797
+ }
798
+ return {
799
+ ...singletonUiInstance,
800
+ row: (args) => {
801
+ logListItem(args);
802
+ }
803
+ };
804
+ }
805
+ var singletonisaacUi;
806
+ function logListItem(args) {
807
+ if (singletonisaacUi === void 0) {
808
+ singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
809
+ }
810
+ singletonisaacUi.div(...args);
811
+ const content = singletonisaacUi.toString();
812
+ singletonisaacUi.rows = [];
813
+ singletonUiInstance?.logger.log(content);
814
+ }
815
+
816
+ // packages/utils/src/lib/file-system.ts
817
+ async function ensureDirectoryExists(baseDir) {
818
+ try {
819
+ await mkdir(baseDir, { recursive: true });
820
+ return;
821
+ } catch (error) {
822
+ ui().logger.info(error.message);
823
+ if (error.code !== "EEXIST") {
824
+ throw error;
825
+ }
826
+ }
827
+ }
828
+ function pluginWorkDir(slug) {
829
+ return join("node_modules", ".code-pushup", slug);
830
+ }
831
+ function filePathToCliArg(path) {
832
+ return `"${path}"`;
833
+ }
834
+
771
835
  // packages/utils/src/lib/text-formats/constants.ts
772
836
  var NEW_LINE = "\n";
773
837
  var TAB = " ";
@@ -1057,60 +1121,6 @@ var html = {
1057
1121
  table
1058
1122
  };
1059
1123
 
1060
- // packages/utils/src/lib/file-system.ts
1061
- import { bundleRequire } from "bundle-require";
1062
- import chalk2 from "chalk";
1063
- import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
1064
- import { join } from "node:path";
1065
-
1066
- // packages/utils/src/lib/logging.ts
1067
- import isaacs_cliui from "@isaacs/cliui";
1068
- import { cliui } from "@poppinss/cliui";
1069
- import chalk from "chalk";
1070
-
1071
- // packages/utils/src/lib/reports/constants.ts
1072
- var TERMINAL_WIDTH = 80;
1073
-
1074
- // packages/utils/src/lib/logging.ts
1075
- var singletonUiInstance;
1076
- function ui() {
1077
- if (singletonUiInstance === void 0) {
1078
- singletonUiInstance = cliui();
1079
- }
1080
- return {
1081
- ...singletonUiInstance,
1082
- row: (args) => {
1083
- logListItem(args);
1084
- }
1085
- };
1086
- }
1087
- var singletonisaacUi;
1088
- function logListItem(args) {
1089
- if (singletonisaacUi === void 0) {
1090
- singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
1091
- }
1092
- singletonisaacUi.div(...args);
1093
- const content = singletonisaacUi.toString();
1094
- singletonisaacUi.rows = [];
1095
- singletonUiInstance?.logger.log(content);
1096
- }
1097
-
1098
- // packages/utils/src/lib/file-system.ts
1099
- async function ensureDirectoryExists(baseDir) {
1100
- try {
1101
- await mkdir(baseDir, { recursive: true });
1102
- return;
1103
- } catch (error) {
1104
- ui().logger.info(error.message);
1105
- if (error.code !== "EEXIST") {
1106
- throw error;
1107
- }
1108
- }
1109
- }
1110
- function pluginWorkDir(slug) {
1111
- return join("node_modules", ".code-pushup", slug);
1112
- }
1113
-
1114
1124
  // packages/utils/src/lib/reports/utils.ts
1115
1125
  var { image: image2, bold: boldMd } = md;
1116
1126
 
@@ -1668,7 +1678,7 @@ async function createRunnerConfig(scriptPath, config) {
1668
1678
  await writeFile(PLUGIN_CONFIG_PATH, JSON.stringify(config));
1669
1679
  return {
1670
1680
  command: "node",
1671
- args: [scriptPath],
1681
+ args: [filePathToCliArg(scriptPath)],
1672
1682
  outputFile: RUNNER_OUTPUT_PATH
1673
1683
  };
1674
1684
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@code-pushup/js-packages-plugin",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "dependencies": {
5
- "@code-pushup/models": "0.45.0",
6
- "@code-pushup/utils": "0.45.0",
5
+ "@code-pushup/models": "0.46.0",
6
+ "@code-pushup/utils": "0.46.0",
7
7
  "semver": "^7.6.0",
8
8
  "zod": "^3.22.4"
9
9
  },
@@ -6,6 +6,14 @@ declare const packageCommandSchema: z.ZodEnum<["audit", "outdated"]>;
6
6
  export type PackageCommand = z.infer<typeof packageCommandSchema>;
7
7
  declare const packageManagerIdSchema: z.ZodEnum<["npm", "yarn-classic", "yarn-modern", "pnpm"]>;
8
8
  export type PackageManagerId = z.infer<typeof packageManagerIdSchema>;
9
+ declare const packageJsonPathSchema: z.ZodDefault<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodObject<{
10
+ autoSearch: z.ZodLiteral<true>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ autoSearch: true;
13
+ }, {
14
+ autoSearch: true;
15
+ }>]>>;
16
+ export type PackageJsonPaths = z.infer<typeof packageJsonPathSchema>;
9
17
  export declare const packageAuditLevels: readonly ["critical", "high", "moderate", "low", "info"];
10
18
  declare const packageAuditLevelSchema: z.ZodEnum<["critical", "high", "moderate", "low", "info"]>;
11
19
  export type PackageAuditLevel = z.infer<typeof packageAuditLevelSchema>;
@@ -15,20 +23,30 @@ export declare const jsPackagesPluginConfigSchema: z.ZodObject<{
15
23
  checks: z.ZodDefault<z.ZodArray<z.ZodEnum<["audit", "outdated"]>, "many">>;
16
24
  packageManager: z.ZodEnum<["npm", "yarn-classic", "yarn-modern", "pnpm"]>;
17
25
  dependencyGroups: z.ZodDefault<z.ZodArray<z.ZodEnum<["prod", "dev", "optional"]>, "many">>;
18
- auditLevelMapping: z.ZodEffects<z.ZodDefault<z.ZodRecord<z.ZodEnum<["critical", "high", "moderate", "low", "info"]>, z.ZodEnum<["info", "warning", "error"]>>>, AuditSeverity, Partial<Record<"info" | "critical" | "high" | "moderate" | "low", "error" | "info" | "warning">> | undefined>;
19
- packageJsonPath: z.ZodDefault<z.ZodString>;
26
+ auditLevelMapping: z.ZodEffects<z.ZodDefault<z.ZodRecord<z.ZodEnum<["critical", "high", "moderate", "low", "info"]>, z.ZodEnum<["info", "warning", "error"]>>>, AuditSeverity, Partial<Record<"info" | "critical" | "high" | "moderate" | "low", "info" | "warning" | "error">> | undefined>;
27
+ packageJsonPaths: z.ZodDefault<z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodObject<{
28
+ autoSearch: z.ZodLiteral<true>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ autoSearch: true;
31
+ }, {
32
+ autoSearch: true;
33
+ }>]>>;
20
34
  }, "strip", z.ZodTypeAny, {
21
35
  checks: ("audit" | "outdated")[];
22
36
  packageManager: "npm" | "pnpm" | "yarn-classic" | "yarn-modern";
23
37
  dependencyGroups: ("prod" | "dev" | "optional")[];
24
38
  auditLevelMapping: AuditSeverity;
25
- packageJsonPath: string;
39
+ packageJsonPaths: string[] | {
40
+ autoSearch: true;
41
+ };
26
42
  }, {
27
43
  packageManager: "npm" | "pnpm" | "yarn-classic" | "yarn-modern";
28
44
  checks?: ("audit" | "outdated")[] | undefined;
29
45
  dependencyGroups?: ("prod" | "dev" | "optional")[] | undefined;
30
- auditLevelMapping?: Partial<Record<"info" | "critical" | "high" | "moderate" | "low", "error" | "info" | "warning">> | undefined;
31
- packageJsonPath?: string | undefined;
46
+ auditLevelMapping?: Partial<Record<"info" | "critical" | "high" | "moderate" | "low", "info" | "warning" | "error">> | undefined;
47
+ packageJsonPaths?: string[] | {
48
+ autoSearch: true;
49
+ } | undefined;
32
50
  }>;
33
51
  export type JSPackagesPluginConfig = z.input<typeof jsPackagesPluginConfigSchema>;
34
52
  export type FinalJSPackagesPluginConfig = z.infer<typeof jsPackagesPluginConfigSchema>;
@@ -4,6 +4,7 @@ export declare const dependencyGroupLong: readonly ["dependencies", "devDependen
4
4
  export type DependencyGroupLong = (typeof dependencyGroupLong)[number];
5
5
  type PackageJsonDependencies = Record<string, string>;
6
6
  export type PackageJson = Partial<Record<DependencyGroupLong, PackageJsonDependencies>>;
7
+ export type DependencyTotals = Record<DependencyGroupLong, number>;
7
8
  export type OutdatedDependency = {
8
9
  name: string;
9
10
  current: string;
@@ -1,3 +1,5 @@
1
1
  import { AuditResult, Vulnerability } from './audit/types';
2
+ import { DependencyTotals } from './outdated/types';
2
3
  export declare function filterAuditResult(result: AuditResult, key: keyof Vulnerability, referenceResult?: AuditResult): AuditResult;
3
- export declare function getTotalDependencies(packageJsonPath: string): Promise<Record<"prod" | "dev" | "optional", number>>;
4
+ export declare function findAllPackageJson(): Promise<string[]>;
5
+ export declare function getTotalDependencies(packageJsonPaths: string[]): Promise<DependencyTotals>;