@code-pushup/js-packages-plugin 0.45.0 → 0.45.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/README.md +1 -1
- package/bin.js +433 -366
- package/index.js +69 -59
- package/package.json +3 -3
- package/src/lib/config.d.ts +23 -3
- package/src/lib/runner/outdated/types.d.ts +1 -0
- package/src/lib/runner/utils.d.ts +3 -1
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) `
|
|
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 ``;
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
1011
|
-
|
|
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
|
-
|
|
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/
|
|
1017
|
-
function
|
|
1018
|
-
return
|
|
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
|
|
1021
|
-
|
|
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/
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
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/
|
|
1030
|
-
|
|
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/
|
|
1033
|
-
|
|
1034
|
-
|
|
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 ``;
|
|
1044
1016
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
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/
|
|
1057
|
-
|
|
1058
|
-
const
|
|
1059
|
-
return
|
|
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
|
-
|
|
1062
|
-
|
|
1063
|
-
return JSON.parse(text);
|
|
1028
|
+
function indentation(text, level = 1) {
|
|
1029
|
+
return `${TAB.repeat(level)}${text}`;
|
|
1064
1030
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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
|
-
|
|
1077
|
-
|
|
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
|
-
|
|
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
|
|
1260
|
-
|
|
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
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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.
|
|
7
|
+
var version = "0.45.1";
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "0.45.1",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"@code-pushup/models": "0.45.
|
|
6
|
-
"@code-pushup/utils": "0.45.
|
|
5
|
+
"@code-pushup/models": "0.45.1",
|
|
6
|
+
"@code-pushup/utils": "0.45.1",
|
|
7
7
|
"semver": "^7.6.0",
|
|
8
8
|
"zod": "^3.22.4"
|
|
9
9
|
},
|
package/src/lib/config.d.ts
CHANGED
|
@@ -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>;
|
|
@@ -16,19 +24,31 @@ export declare const jsPackagesPluginConfigSchema: z.ZodObject<{
|
|
|
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
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", "error" | "info" | "warning">> | undefined>;
|
|
19
|
-
|
|
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
|
-
|
|
39
|
+
packageJsonPaths: (string[] | {
|
|
40
|
+
autoSearch: true;
|
|
41
|
+
}) & (string[] | {
|
|
42
|
+
autoSearch: true;
|
|
43
|
+
} | undefined);
|
|
26
44
|
}, {
|
|
27
45
|
packageManager: "npm" | "pnpm" | "yarn-classic" | "yarn-modern";
|
|
28
46
|
checks?: ("audit" | "outdated")[] | undefined;
|
|
29
47
|
dependencyGroups?: ("prod" | "dev" | "optional")[] | undefined;
|
|
30
48
|
auditLevelMapping?: Partial<Record<"info" | "critical" | "high" | "moderate" | "low", "error" | "info" | "warning">> | undefined;
|
|
31
|
-
|
|
49
|
+
packageJsonPaths?: string[] | {
|
|
50
|
+
autoSearch: true;
|
|
51
|
+
} | undefined;
|
|
32
52
|
}>;
|
|
33
53
|
export type JSPackagesPluginConfig = z.input<typeof jsPackagesPluginConfigSchema>;
|
|
34
54
|
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
|
|
4
|
+
export declare function findAllPackageJson(): Promise<string[]>;
|
|
5
|
+
export declare function getTotalDependencies(packageJsonPaths: string[]): Promise<DependencyTotals>;
|