@code-pushup/js-packages-plugin 0.29.0 → 0.34.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/CONTRIBUTING.md +10 -0
- package/README.md +7 -2
- package/bin.js +462 -76
- package/index.js +21 -12
- package/package.json +3 -3
- package/src/lib/config.d.ts +4 -3
- package/src/lib/constants.d.ts +3 -0
- package/src/lib/runner/audit/constants.d.ts +5 -1
- package/src/lib/runner/audit/transform.d.ts +7 -7
- package/src/lib/runner/audit/types.d.ts +87 -11
- package/src/lib/runner/audit/unify-type.d.ts +8 -0
- package/src/lib/runner/outdated/constants.d.ts +4 -1
- package/src/lib/runner/outdated/transform.d.ts +6 -6
- package/src/lib/runner/outdated/types.d.ts +47 -8
- package/src/lib/runner/outdated/unify-type.d.ts +5 -0
- package/src/lib/runner/utils.d.ts +2 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Contributing to js-packages
|
|
2
|
+
|
|
3
|
+
## Adding new package managers
|
|
4
|
+
|
|
5
|
+
In order to add a support for a new package manager, one needs to do the following.
|
|
6
|
+
|
|
7
|
+
1. Expand `packageManagerSchema` in `config.ts`.
|
|
8
|
+
2. Expand `<command>Args` in `runner/<command>/constants.ts` with a set of arguments to be run for a given package manager command.
|
|
9
|
+
3. Create a custom type in `runner/<command>/types.ts` with relevant properties based on expected command JSON output.
|
|
10
|
+
4. Create a function in `runner/<command>/unify-type.ts` that will transform JSON output into a normalized type `OutdatedResult` or `AuditResult` and add it to `normalized<command>Mapper` in `runner/<command>/constants.ts`.
|
package/README.md
CHANGED
|
@@ -10,9 +10,14 @@ This plugin checks for known vulnerabilities and outdated dependencies.
|
|
|
10
10
|
It supports the following package managers:
|
|
11
11
|
|
|
12
12
|
- [NPM](https://docs.npmjs.com/)
|
|
13
|
-
- [Yarn v1](https://classic.yarnpkg.com/docs/)
|
|
13
|
+
- [Yarn v1](https://classic.yarnpkg.com/docs/)
|
|
14
|
+
- [Yarn v2+](https://yarnpkg.com/getting-started)
|
|
15
|
+
- In order to check outdated dependencies for Yarn v2+, you need to install [`yarn-plugin-outdated`](https://github.com/mskelton/yarn-plugin-outdated).
|
|
14
16
|
- [PNPM](https://pnpm.io/pnpm-cli)
|
|
15
17
|
|
|
18
|
+
> ![NOTE]
|
|
19
|
+
> As of now, Yarn v2 does not support security audit of optional dependencies. Only production and dev dependencies audits will be included in the report.
|
|
20
|
+
|
|
16
21
|
## Getting started
|
|
17
22
|
|
|
18
23
|
1. If you haven't already, install [@code-pushup/cli](../cli/README.md) and create a configuration file.
|
|
@@ -97,7 +102,7 @@ The plugin accepts the following parameters:
|
|
|
97
102
|
|
|
98
103
|
### Audits and group
|
|
99
104
|
|
|
100
|
-
This plugin provides a group per check for a convenient declaration in your config.
|
|
105
|
+
This plugin provides a group per check for a convenient declaration in your config. Each group contains audits for all supported groups of dependencies (`prod`, `dev` and `optional`).
|
|
101
106
|
|
|
102
107
|
```ts
|
|
103
108
|
// ...
|
package/bin.js
CHANGED
|
@@ -657,6 +657,20 @@ import chalk2 from "chalk";
|
|
|
657
657
|
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
658
658
|
import { join } from "node:path";
|
|
659
659
|
|
|
660
|
+
// packages/utils/src/lib/formatting.ts
|
|
661
|
+
function pluralize(text, amount) {
|
|
662
|
+
if (amount != null && Math.abs(amount) === 1) {
|
|
663
|
+
return text;
|
|
664
|
+
}
|
|
665
|
+
if (text.endsWith("y")) {
|
|
666
|
+
return `${text.slice(0, -1)}ies`;
|
|
667
|
+
}
|
|
668
|
+
if (text.endsWith("s")) {
|
|
669
|
+
return `${text}es`;
|
|
670
|
+
}
|
|
671
|
+
return `${text}s`;
|
|
672
|
+
}
|
|
673
|
+
|
|
660
674
|
// packages/utils/src/lib/guards.ts
|
|
661
675
|
function isPromiseFulfilledResult(result) {
|
|
662
676
|
return result.status === "fulfilled";
|
|
@@ -739,7 +753,7 @@ var ProcessError = class extends Error {
|
|
|
739
753
|
}
|
|
740
754
|
};
|
|
741
755
|
function executeProcess(cfg) {
|
|
742
|
-
const { observer, cwd, command, args,
|
|
756
|
+
const { observer, cwd, command, args, ignoreExitCode = false } = cfg;
|
|
743
757
|
const { onStdout, onError, onComplete } = observer ?? {};
|
|
744
758
|
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
745
759
|
const start = performance.now();
|
|
@@ -759,7 +773,7 @@ function executeProcess(cfg) {
|
|
|
759
773
|
});
|
|
760
774
|
process2.on("close", (code) => {
|
|
761
775
|
const timings = { date, duration: calcDuration(start) };
|
|
762
|
-
if (code === 0 ||
|
|
776
|
+
if (code === 0 || ignoreExitCode) {
|
|
763
777
|
onComplete?.();
|
|
764
778
|
resolve({ code, stdout, stderr, ...timings });
|
|
765
779
|
} else {
|
|
@@ -775,9 +789,25 @@ function executeProcess(cfg) {
|
|
|
775
789
|
import { simpleGit } from "simple-git";
|
|
776
790
|
|
|
777
791
|
// packages/utils/src/lib/transform.ts
|
|
792
|
+
import { platform } from "node:os";
|
|
778
793
|
function objectToEntries(obj) {
|
|
779
794
|
return Object.entries(obj);
|
|
780
795
|
}
|
|
796
|
+
function objectFromEntries(entries) {
|
|
797
|
+
return Object.fromEntries(entries);
|
|
798
|
+
}
|
|
799
|
+
function toUnixNewlines(text) {
|
|
800
|
+
return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
|
|
801
|
+
}
|
|
802
|
+
function fromJsonLines(jsonLines) {
|
|
803
|
+
const unifiedNewLines = toUnixNewlines(jsonLines).trim();
|
|
804
|
+
return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
|
|
805
|
+
}
|
|
806
|
+
function apostrophize(text, upperCase) {
|
|
807
|
+
const lastCharMatch = text.match(/(\w)\W*$/);
|
|
808
|
+
const lastChar = lastCharMatch?.[1] ?? "";
|
|
809
|
+
return `${text}'${lastChar.toLocaleLowerCase() === "s" ? "" : upperCase ? "S" : "s"}`;
|
|
810
|
+
}
|
|
781
811
|
|
|
782
812
|
// packages/utils/src/lib/progress.ts
|
|
783
813
|
import chalk3 from "chalk";
|
|
@@ -797,6 +827,17 @@ var defaultAuditLevelMapping = {
|
|
|
797
827
|
low: "warning",
|
|
798
828
|
info: "info"
|
|
799
829
|
};
|
|
830
|
+
var dependencyGroupToLong = {
|
|
831
|
+
prod: "dependencies",
|
|
832
|
+
dev: "devDependencies",
|
|
833
|
+
optional: "optionalDependencies"
|
|
834
|
+
};
|
|
835
|
+
var pkgManagerCommands = {
|
|
836
|
+
npm: "npm",
|
|
837
|
+
"yarn-classic": "yarn",
|
|
838
|
+
"yarn-modern": "yarn",
|
|
839
|
+
pnpm: "pnpm"
|
|
840
|
+
};
|
|
800
841
|
|
|
801
842
|
// packages/plugin-js-packages/src/lib/config.ts
|
|
802
843
|
var dependencyGroups = ["prod", "dev", "optional"];
|
|
@@ -834,6 +875,218 @@ var jsPackagesPluginConfigSchema = z15.object({
|
|
|
834
875
|
}).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping)
|
|
835
876
|
});
|
|
836
877
|
|
|
878
|
+
// packages/plugin-js-packages/src/lib/runner/utils.ts
|
|
879
|
+
function filterAuditResult(result, key, referenceResult) {
|
|
880
|
+
if (result.vulnerabilities.length === 0) {
|
|
881
|
+
return result;
|
|
882
|
+
}
|
|
883
|
+
const uniqueResult = result.vulnerabilities.reduce(
|
|
884
|
+
(acc, ref) => {
|
|
885
|
+
const matchReference = referenceResult ?? acc;
|
|
886
|
+
const isMatch = matchReference.vulnerabilities.map((vulnerability) => vulnerability[key]).includes(ref[key]);
|
|
887
|
+
if (isMatch) {
|
|
888
|
+
return {
|
|
889
|
+
vulnerabilities: acc.vulnerabilities,
|
|
890
|
+
summary: {
|
|
891
|
+
...acc.summary,
|
|
892
|
+
[ref.severity]: acc.summary[ref.severity] - 1,
|
|
893
|
+
total: acc.summary.total - 1
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
return {
|
|
898
|
+
vulnerabilities: [...acc.vulnerabilities, ref],
|
|
899
|
+
summary: acc.summary
|
|
900
|
+
};
|
|
901
|
+
},
|
|
902
|
+
{ vulnerabilities: [], summary: result.summary }
|
|
903
|
+
);
|
|
904
|
+
return {
|
|
905
|
+
vulnerabilities: uniqueResult.vulnerabilities,
|
|
906
|
+
summary: uniqueResult.summary
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// packages/plugin-js-packages/src/lib/runner/audit/unify-type.ts
|
|
911
|
+
function npmToAuditResult(output) {
|
|
912
|
+
const npmAudit = JSON.parse(output);
|
|
913
|
+
const vulnerabilities = objectToEntries(npmAudit.vulnerabilities).map(
|
|
914
|
+
([name, detail]) => {
|
|
915
|
+
const advisory = npmToAdvisory(name, npmAudit.vulnerabilities);
|
|
916
|
+
return {
|
|
917
|
+
name: name.toString(),
|
|
918
|
+
severity: detail.severity,
|
|
919
|
+
versionRange: detail.range,
|
|
920
|
+
directDependency: detail.isDirect ? true : detail.effects[0] ?? "",
|
|
921
|
+
fixInformation: npmToFixInformation(detail.fixAvailable),
|
|
922
|
+
...advisory != null && {
|
|
923
|
+
title: advisory.title,
|
|
924
|
+
url: advisory.url
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
return {
|
|
930
|
+
vulnerabilities,
|
|
931
|
+
summary: npmAudit.metadata.vulnerabilities
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
function npmToFixInformation(fixAvailable) {
|
|
935
|
+
if (typeof fixAvailable === "boolean") {
|
|
936
|
+
return fixAvailable ? "Fix is available." : "";
|
|
937
|
+
}
|
|
938
|
+
return `Fix available: Update \`${fixAvailable.name}\` to version **${fixAvailable.version}**${fixAvailable.isSemVerMajor ? " (breaking change)." : "."}`;
|
|
939
|
+
}
|
|
940
|
+
function npmToAdvisory(name, vulnerabilities, prevNodes = /* @__PURE__ */ new Set()) {
|
|
941
|
+
const advisory = vulnerabilities[name]?.via;
|
|
942
|
+
if (Array.isArray(advisory) && advisory.length > 0 && typeof advisory[0] === "object") {
|
|
943
|
+
return { title: advisory[0].title, url: advisory[0].url };
|
|
944
|
+
}
|
|
945
|
+
if (Array.isArray(advisory) && advisory.length > 0 && advisory.every((value) => typeof value === "string")) {
|
|
946
|
+
let advisoryInfo = null;
|
|
947
|
+
let newReferences = [];
|
|
948
|
+
let advisoryInfoFound = false;
|
|
949
|
+
for (const via of advisory) {
|
|
950
|
+
if (!prevNodes.has(via)) {
|
|
951
|
+
newReferences.push(via);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
while (newReferences.length > 0 && !advisoryInfoFound) {
|
|
955
|
+
const ref = newReferences.pop();
|
|
956
|
+
prevNodes.add(ref);
|
|
957
|
+
const result = npmToAdvisory(ref, vulnerabilities, prevNodes);
|
|
958
|
+
if (result != null) {
|
|
959
|
+
advisoryInfo = { title: result.title, url: result.url };
|
|
960
|
+
advisoryInfoFound = true;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
return advisoryInfo;
|
|
964
|
+
}
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
function yarnv1ToAuditResult(output) {
|
|
968
|
+
const yarnv1Result = fromJsonLines(output);
|
|
969
|
+
const [yarnv1Advisory, yarnv1Summary] = validateYarnv1Result(yarnv1Result);
|
|
970
|
+
const vulnerabilities = yarnv1Advisory.map(
|
|
971
|
+
({ data: { resolution, advisory } }) => {
|
|
972
|
+
const { id, path } = resolution;
|
|
973
|
+
const directDependency = path.slice(0, path.indexOf(">"));
|
|
974
|
+
const {
|
|
975
|
+
module_name: name,
|
|
976
|
+
title,
|
|
977
|
+
url,
|
|
978
|
+
severity,
|
|
979
|
+
vulnerable_versions: versionRange,
|
|
980
|
+
recommendation: fixInformation
|
|
981
|
+
} = advisory;
|
|
982
|
+
return {
|
|
983
|
+
name,
|
|
984
|
+
title,
|
|
985
|
+
id,
|
|
986
|
+
url,
|
|
987
|
+
severity,
|
|
988
|
+
versionRange,
|
|
989
|
+
directDependency: name === directDependency ? true : directDependency,
|
|
990
|
+
fixInformation
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
);
|
|
994
|
+
const summary = {
|
|
995
|
+
...yarnv1Summary.data.vulnerabilities,
|
|
996
|
+
total: Object.values(yarnv1Summary.data.vulnerabilities).reduce(
|
|
997
|
+
(acc, amount) => acc + amount,
|
|
998
|
+
0
|
|
999
|
+
)
|
|
1000
|
+
};
|
|
1001
|
+
return filterAuditResult({ vulnerabilities, summary }, "id");
|
|
1002
|
+
}
|
|
1003
|
+
function validateYarnv1Result(result) {
|
|
1004
|
+
const summary = result.at(-1);
|
|
1005
|
+
if (summary?.type !== "auditSummary") {
|
|
1006
|
+
throw new Error("Invalid Yarn v1 audit result - no summary found.");
|
|
1007
|
+
}
|
|
1008
|
+
const vulnerabilities = result.filter(
|
|
1009
|
+
(item) => item.type === "auditAdvisory"
|
|
1010
|
+
);
|
|
1011
|
+
return [vulnerabilities, summary];
|
|
1012
|
+
}
|
|
1013
|
+
function yarnv2ToAuditResult(output) {
|
|
1014
|
+
const yarnv2Audit = JSON.parse(output);
|
|
1015
|
+
const vulnerabilities = Object.values(yarnv2Audit.advisories).map(
|
|
1016
|
+
({
|
|
1017
|
+
module_name: name,
|
|
1018
|
+
severity,
|
|
1019
|
+
title,
|
|
1020
|
+
url,
|
|
1021
|
+
vulnerable_versions: versionRange,
|
|
1022
|
+
recommendation: fixInformation,
|
|
1023
|
+
findings
|
|
1024
|
+
}) => {
|
|
1025
|
+
const directDep = findings[0]?.paths[0];
|
|
1026
|
+
return {
|
|
1027
|
+
name,
|
|
1028
|
+
severity,
|
|
1029
|
+
title,
|
|
1030
|
+
url,
|
|
1031
|
+
versionRange,
|
|
1032
|
+
fixInformation,
|
|
1033
|
+
directDependency: directDep != null && directDep !== name ? directDep : true
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
);
|
|
1037
|
+
return {
|
|
1038
|
+
vulnerabilities,
|
|
1039
|
+
summary: {
|
|
1040
|
+
...yarnv2Audit.metadata.vulnerabilities,
|
|
1041
|
+
total: getVulnerabilitiesTotal(yarnv2Audit.metadata.vulnerabilities)
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
function pnpmToAuditResult(output) {
|
|
1046
|
+
const pnpmResult = JSON.parse(output);
|
|
1047
|
+
const vulnerabilities = Object.values(pnpmResult.advisories).map(
|
|
1048
|
+
({
|
|
1049
|
+
module_name: name,
|
|
1050
|
+
id,
|
|
1051
|
+
title,
|
|
1052
|
+
url,
|
|
1053
|
+
severity,
|
|
1054
|
+
vulnerable_versions: versionRange,
|
|
1055
|
+
recommendation: fixInformation,
|
|
1056
|
+
findings
|
|
1057
|
+
}) => {
|
|
1058
|
+
const path = findings[0]?.paths[0];
|
|
1059
|
+
return {
|
|
1060
|
+
name,
|
|
1061
|
+
id,
|
|
1062
|
+
title,
|
|
1063
|
+
url,
|
|
1064
|
+
severity,
|
|
1065
|
+
versionRange,
|
|
1066
|
+
directDependency: path == null ? true : pnpmToDirectDependency(path),
|
|
1067
|
+
fixInformation
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
return {
|
|
1072
|
+
vulnerabilities,
|
|
1073
|
+
summary: {
|
|
1074
|
+
...pnpmResult.metadata.vulnerabilities,
|
|
1075
|
+
total: getVulnerabilitiesTotal(pnpmResult.metadata.vulnerabilities)
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
function pnpmToDirectDependency(path) {
|
|
1080
|
+
const deps = path.split(" > ").slice(1);
|
|
1081
|
+
if (deps.length <= 1) {
|
|
1082
|
+
return true;
|
|
1083
|
+
}
|
|
1084
|
+
return deps[0]?.split("@")[0] ?? true;
|
|
1085
|
+
}
|
|
1086
|
+
function getVulnerabilitiesTotal(summary) {
|
|
1087
|
+
return Object.values(summary).reduce((acc, value) => acc + value, 0);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
837
1090
|
// packages/plugin-js-packages/src/lib/runner/audit/constants.ts
|
|
838
1091
|
var auditScoreModifiers = {
|
|
839
1092
|
critical: 1,
|
|
@@ -842,20 +1095,65 @@ var auditScoreModifiers = {
|
|
|
842
1095
|
low: 0.02,
|
|
843
1096
|
info: 0.01
|
|
844
1097
|
};
|
|
1098
|
+
var normalizeAuditMapper = {
|
|
1099
|
+
npm: npmToAuditResult,
|
|
1100
|
+
"yarn-classic": yarnv1ToAuditResult,
|
|
1101
|
+
"yarn-modern": yarnv2ToAuditResult,
|
|
1102
|
+
pnpm: pnpmToAuditResult
|
|
1103
|
+
};
|
|
1104
|
+
var filterNpmAuditResults = (results) => ({
|
|
1105
|
+
prod: results.prod,
|
|
1106
|
+
dev: filterAuditResult(results.dev, "name", results.prod),
|
|
1107
|
+
optional: filterAuditResult(results.optional, "name", results.prod)
|
|
1108
|
+
});
|
|
1109
|
+
var filterPnpmAuditResults = (results) => ({
|
|
1110
|
+
prod: results.prod,
|
|
1111
|
+
dev: results.dev,
|
|
1112
|
+
optional: filterAuditResult(
|
|
1113
|
+
filterAuditResult(results.optional, "id", results.prod),
|
|
1114
|
+
"id",
|
|
1115
|
+
results.dev
|
|
1116
|
+
)
|
|
1117
|
+
});
|
|
1118
|
+
var postProcessingAuditMapper = {
|
|
1119
|
+
npm: filterNpmAuditResults,
|
|
1120
|
+
// prod dependencies need to be filtered out manually since v10
|
|
1121
|
+
pnpm: filterPnpmAuditResults
|
|
1122
|
+
// optional dependencies don't have an exclusive option so they need duplicates filtered out
|
|
1123
|
+
};
|
|
1124
|
+
var npmDependencyOptions = {
|
|
1125
|
+
prod: ["--omit=dev", "--omit=optional"],
|
|
1126
|
+
dev: ["--include=dev", "--omit=optional"],
|
|
1127
|
+
optional: ["--include=optional", "--omit=dev"]
|
|
1128
|
+
};
|
|
1129
|
+
var yarnv2EnvironmentOptions = {
|
|
1130
|
+
prod: "production",
|
|
1131
|
+
dev: "development",
|
|
1132
|
+
optional: ""
|
|
1133
|
+
};
|
|
1134
|
+
var pnpmDependencyOptions = {
|
|
1135
|
+
prod: ["--prod", "--no-optional"],
|
|
1136
|
+
dev: ["--dev", "--no-optional"],
|
|
1137
|
+
optional: []
|
|
1138
|
+
};
|
|
1139
|
+
var auditArgs = (groupDep) => ({
|
|
1140
|
+
npm: [...npmDependencyOptions[groupDep], "--audit-level=none"],
|
|
1141
|
+
"yarn-classic": ["--groups", dependencyGroupToLong[groupDep]],
|
|
1142
|
+
"yarn-modern": ["--environment", yarnv2EnvironmentOptions[groupDep]],
|
|
1143
|
+
pnpm: [...pnpmDependencyOptions[groupDep]]
|
|
1144
|
+
});
|
|
845
1145
|
|
|
846
1146
|
// packages/plugin-js-packages/src/lib/runner/audit/transform.ts
|
|
847
|
-
function auditResultToAuditOutput(result, dependenciesType, auditLevelMapping) {
|
|
1147
|
+
function auditResultToAuditOutput(result, packageManager, dependenciesType, auditLevelMapping) {
|
|
848
1148
|
const issues = vulnerabilitiesToIssues(
|
|
849
1149
|
result.vulnerabilities,
|
|
850
1150
|
auditLevelMapping
|
|
851
1151
|
);
|
|
852
1152
|
return {
|
|
853
|
-
slug:
|
|
854
|
-
score: calculateAuditScore(result.
|
|
855
|
-
value: result.
|
|
856
|
-
displayValue:
|
|
857
|
-
result.metadata.vulnerabilities
|
|
858
|
-
),
|
|
1153
|
+
slug: `${packageManager}-audit-${dependenciesType}`,
|
|
1154
|
+
score: calculateAuditScore(result.summary),
|
|
1155
|
+
value: result.summary.total,
|
|
1156
|
+
displayValue: summaryToDisplayValue(result.summary),
|
|
859
1157
|
...issues.length > 0 && { details: { issues } }
|
|
860
1158
|
};
|
|
861
1159
|
}
|
|
@@ -874,31 +1172,26 @@ function calculateAuditScore(stats) {
|
|
|
874
1172
|
1
|
|
875
1173
|
);
|
|
876
1174
|
}
|
|
877
|
-
function
|
|
878
|
-
if (
|
|
1175
|
+
function summaryToDisplayValue(summary) {
|
|
1176
|
+
if (summary.total === 0) {
|
|
879
1177
|
return "0 vulnerabilities";
|
|
880
1178
|
}
|
|
881
|
-
const vulnerabilityStats = packageAuditLevels.map(
|
|
882
|
-
|
|
883
|
-
).filter((text) => text !== "").join(", ");
|
|
884
|
-
return `${vulnerabilities.total} ${vulnerabilities.total === 1 ? "vulnerability" : "vulnerabilities"} (${vulnerabilityStats})`;
|
|
1179
|
+
const vulnerabilityStats = packageAuditLevels.map((level) => summary[level] > 0 ? `${summary[level]} ${level}` : "").filter((text) => text !== "").join(", ");
|
|
1180
|
+
return `${summary.total} ${summary.total === 1 ? "vulnerability" : "vulnerabilities"} (${vulnerabilityStats})`;
|
|
885
1181
|
}
|
|
886
1182
|
function vulnerabilitiesToIssues(vulnerabilities, auditLevelMapping) {
|
|
887
|
-
if (
|
|
1183
|
+
if (vulnerabilities.length === 0) {
|
|
888
1184
|
return [];
|
|
889
1185
|
}
|
|
890
|
-
return
|
|
891
|
-
const versionRange = detail.
|
|
892
|
-
const
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
severity: auditLevelMapping[detail.severity]
|
|
898
|
-
};
|
|
899
|
-
}
|
|
1186
|
+
return vulnerabilities.map((detail) => {
|
|
1187
|
+
const versionRange = detail.versionRange === "*" ? "**all** versions" : `versions **${detail.versionRange}**`;
|
|
1188
|
+
const directDependency = typeof detail.directDependency === "string" ? `\`${detail.directDependency}\`` : "";
|
|
1189
|
+
const depHierarchy = directDependency === "" ? `\`${detail.name}\` dependency` : `${apostrophize(directDependency)} dependency \`${detail.name}\``;
|
|
1190
|
+
const vulnerabilitySummary = `has a **${detail.severity}** vulnerability in ${versionRange}.`;
|
|
1191
|
+
const fixInfo = detail.fixInformation ? ` ${detail.fixInformation}` : "";
|
|
1192
|
+
const additionalInfo = detail.title != null && detail.url != null ? ` More information: [${detail.title}](${detail.url})` : "";
|
|
900
1193
|
return {
|
|
901
|
-
message: `${
|
|
1194
|
+
message: `${depHierarchy} ${vulnerabilitySummary}${fixInfo}${additionalInfo}`,
|
|
902
1195
|
severity: auditLevelMapping[detail.severity]
|
|
903
1196
|
};
|
|
904
1197
|
});
|
|
@@ -914,67 +1207,140 @@ var PLUGIN_CONFIG_PATH = join2(
|
|
|
914
1207
|
"plugin-config.json"
|
|
915
1208
|
);
|
|
916
1209
|
|
|
1210
|
+
// packages/plugin-js-packages/src/lib/runner/outdated/unify-type.ts
|
|
1211
|
+
function npmToOutdatedResult(output) {
|
|
1212
|
+
const npmOutdated = JSON.parse(output);
|
|
1213
|
+
return objectToEntries(npmOutdated).filter(
|
|
1214
|
+
(entry) => entry[1].current != null
|
|
1215
|
+
).map(([name, overview]) => ({
|
|
1216
|
+
name,
|
|
1217
|
+
current: overview.current,
|
|
1218
|
+
latest: overview.latest,
|
|
1219
|
+
type: overview.type,
|
|
1220
|
+
...overview.homepage != null && { url: overview.homepage }
|
|
1221
|
+
}));
|
|
1222
|
+
}
|
|
1223
|
+
function yarnv1ToOutdatedResult(output) {
|
|
1224
|
+
const yarnv1Outdated = fromJsonLines(output);
|
|
1225
|
+
const dependencies = yarnv1Outdated[1].data.body;
|
|
1226
|
+
return dependencies.map(([name, current, _, latest, __, type, url]) => ({
|
|
1227
|
+
name,
|
|
1228
|
+
current,
|
|
1229
|
+
latest,
|
|
1230
|
+
type,
|
|
1231
|
+
url
|
|
1232
|
+
}));
|
|
1233
|
+
}
|
|
1234
|
+
function yarnv2ToOutdatedResult(output) {
|
|
1235
|
+
const npmOutdated = JSON.parse(output);
|
|
1236
|
+
return npmOutdated.map(({ name, current, latest, type }) => ({
|
|
1237
|
+
name,
|
|
1238
|
+
current,
|
|
1239
|
+
latest,
|
|
1240
|
+
type
|
|
1241
|
+
}));
|
|
1242
|
+
}
|
|
1243
|
+
function pnpmToOutdatedResult(output) {
|
|
1244
|
+
const pnpmOutdated = JSON.parse(output);
|
|
1245
|
+
return objectToEntries(pnpmOutdated).map(
|
|
1246
|
+
([name, { current, latest, dependencyType: type }]) => ({
|
|
1247
|
+
name,
|
|
1248
|
+
current,
|
|
1249
|
+
latest,
|
|
1250
|
+
type
|
|
1251
|
+
})
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
|
|
917
1255
|
// packages/plugin-js-packages/src/lib/runner/outdated/constants.ts
|
|
918
1256
|
var outdatedSeverity = {
|
|
919
1257
|
major: "error",
|
|
920
1258
|
minor: "warning",
|
|
921
1259
|
patch: "info"
|
|
922
1260
|
};
|
|
1261
|
+
var normalizeOutdatedMapper = {
|
|
1262
|
+
npm: npmToOutdatedResult,
|
|
1263
|
+
"yarn-classic": yarnv1ToOutdatedResult,
|
|
1264
|
+
"yarn-modern": yarnv2ToOutdatedResult,
|
|
1265
|
+
pnpm: pnpmToOutdatedResult
|
|
1266
|
+
};
|
|
1267
|
+
var outdatedArgs = {
|
|
1268
|
+
npm: ["--long"],
|
|
1269
|
+
"yarn-classic": [],
|
|
1270
|
+
"yarn-modern": [],
|
|
1271
|
+
pnpm: []
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// packages/plugin-js-packages/src/lib/runner/outdated/types.ts
|
|
1275
|
+
var versionType = ["major", "minor", "patch"];
|
|
923
1276
|
|
|
924
1277
|
// packages/plugin-js-packages/src/lib/runner/outdated/transform.ts
|
|
925
|
-
function outdatedResultToAuditOutput(result,
|
|
926
|
-
const
|
|
927
|
-
(
|
|
928
|
-
)
|
|
929
|
-
|
|
1278
|
+
function outdatedResultToAuditOutput(result, packageManager, dependencyGroup) {
|
|
1279
|
+
const relevantDependencies = result.filter(
|
|
1280
|
+
(dep) => dep.type === dependencyGroupToLong[dependencyGroup]
|
|
1281
|
+
);
|
|
1282
|
+
const outdatedDependencies = relevantDependencies.filter(
|
|
1283
|
+
(dep) => dep.current !== dep.latest
|
|
930
1284
|
);
|
|
931
|
-
const
|
|
932
|
-
(
|
|
1285
|
+
const outdatedStats = outdatedDependencies.reduce(
|
|
1286
|
+
(acc, dep) => {
|
|
1287
|
+
const outdatedLevel = getOutdatedLevel(dep.current, dep.latest);
|
|
1288
|
+
return { ...acc, [outdatedLevel]: acc[outdatedLevel] + 1 };
|
|
1289
|
+
},
|
|
1290
|
+
{ major: 0, minor: 0, patch: 0 }
|
|
933
1291
|
);
|
|
934
|
-
const majorOutdatedAmount = outdatedDependencies.filter(
|
|
935
|
-
([, versions]) => getOutdatedLevel(versions.current, versions.wanted) === "major"
|
|
936
|
-
).length;
|
|
937
1292
|
const issues = outdatedDependencies.length === 0 ? [] : outdatedToIssues(outdatedDependencies);
|
|
938
1293
|
return {
|
|
939
|
-
slug:
|
|
1294
|
+
slug: `${packageManager}-outdated-${dependencyGroup}`,
|
|
940
1295
|
score: calculateOutdatedScore(
|
|
941
|
-
|
|
942
|
-
|
|
1296
|
+
outdatedStats.major,
|
|
1297
|
+
relevantDependencies.length
|
|
943
1298
|
),
|
|
944
1299
|
value: outdatedDependencies.length,
|
|
945
|
-
displayValue: outdatedToDisplayValue(
|
|
946
|
-
majorOutdatedAmount,
|
|
947
|
-
outdatedDependencies.length
|
|
948
|
-
),
|
|
1300
|
+
displayValue: outdatedToDisplayValue(outdatedStats),
|
|
949
1301
|
...issues.length > 0 && { details: { issues } }
|
|
950
1302
|
};
|
|
951
1303
|
}
|
|
952
1304
|
function calculateOutdatedScore(majorOutdated, totalDeps) {
|
|
953
1305
|
return totalDeps > 0 ? (totalDeps - majorOutdated) / totalDeps : 1;
|
|
954
1306
|
}
|
|
955
|
-
function outdatedToDisplayValue(
|
|
956
|
-
|
|
1307
|
+
function outdatedToDisplayValue(stats) {
|
|
1308
|
+
const total = stats.major + stats.minor + stats.patch;
|
|
1309
|
+
const versionBreakdown = versionType.map((version) => stats[version] > 0 ? `${stats[version]} ${version}` : "").filter((text) => text !== "");
|
|
1310
|
+
if (versionBreakdown.length === 0) {
|
|
1311
|
+
return "all dependencies are up to date";
|
|
1312
|
+
}
|
|
1313
|
+
if (versionBreakdown.length > 1) {
|
|
1314
|
+
return `${total} outdated package versions (${versionBreakdown.join(
|
|
1315
|
+
", "
|
|
1316
|
+
)})`;
|
|
1317
|
+
}
|
|
1318
|
+
return `${versionBreakdown[0]} outdated package ${pluralize(
|
|
1319
|
+
"version",
|
|
1320
|
+
total
|
|
1321
|
+
)}`;
|
|
957
1322
|
}
|
|
958
1323
|
function outdatedToIssues(dependencies) {
|
|
959
|
-
return dependencies.map((
|
|
960
|
-
const
|
|
961
|
-
const
|
|
1324
|
+
return dependencies.map((dep) => {
|
|
1325
|
+
const { name, current, latest, url } = dep;
|
|
1326
|
+
const outdatedLevel = getOutdatedLevel(current, latest);
|
|
1327
|
+
const packageReference = url == null ? `\`${name}\`` : `[\`${name}\`](${url})`;
|
|
962
1328
|
return {
|
|
963
|
-
message: `Package ${packageReference} requires a **${outdatedLevel}** update from **${
|
|
1329
|
+
message: `Package ${packageReference} requires a **${outdatedLevel}** update from **${current}** to **${latest}**.`,
|
|
964
1330
|
severity: outdatedSeverity[outdatedLevel]
|
|
965
1331
|
};
|
|
966
1332
|
});
|
|
967
1333
|
}
|
|
968
|
-
function getOutdatedLevel(currentFullVersion,
|
|
1334
|
+
function getOutdatedLevel(currentFullVersion, latestFullVersion) {
|
|
969
1335
|
const current = splitPackageVersion(currentFullVersion);
|
|
970
|
-
const
|
|
971
|
-
if (current.major <
|
|
1336
|
+
const latest = splitPackageVersion(latestFullVersion);
|
|
1337
|
+
if (current.major < latest.major) {
|
|
972
1338
|
return "major";
|
|
973
1339
|
}
|
|
974
|
-
if (current.minor <
|
|
1340
|
+
if (current.minor < latest.minor) {
|
|
975
1341
|
return "minor";
|
|
976
1342
|
}
|
|
977
|
-
if (current.patch <
|
|
1343
|
+
if (current.patch < latest.patch) {
|
|
978
1344
|
return "patch";
|
|
979
1345
|
}
|
|
980
1346
|
throw new Error("Package is not outdated.");
|
|
@@ -998,42 +1364,62 @@ async function executeRunner() {
|
|
|
998
1364
|
}
|
|
999
1365
|
async function processOutdated(packageManager) {
|
|
1000
1366
|
const { stdout } = await executeProcess({
|
|
1001
|
-
command: packageManager,
|
|
1002
|
-
args: ["outdated", "--json",
|
|
1003
|
-
|
|
1004
|
-
|
|
1367
|
+
command: pkgManagerCommands[packageManager],
|
|
1368
|
+
args: ["outdated", "--json", ...outdatedArgs[packageManager]],
|
|
1369
|
+
cwd: process.cwd(),
|
|
1370
|
+
ignoreExitCode: true
|
|
1371
|
+
// outdated returns exit code 1 when outdated dependencies are found
|
|
1005
1372
|
});
|
|
1006
|
-
const
|
|
1373
|
+
const normalizedResult = normalizeOutdatedMapper[packageManager](stdout);
|
|
1007
1374
|
return dependencyGroups.map(
|
|
1008
|
-
(dep) => outdatedResultToAuditOutput(
|
|
1375
|
+
(dep) => outdatedResultToAuditOutput(normalizedResult, packageManager, dep)
|
|
1009
1376
|
);
|
|
1010
1377
|
}
|
|
1011
1378
|
async function processAudit(packageManager, auditLevelMapping) {
|
|
1379
|
+
const supportedDepGroups = packageManager === "yarn-modern" ? dependencyGroups.filter((dep) => dep !== "optional") : dependencyGroups;
|
|
1012
1380
|
const auditResults = await Promise.allSettled(
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1381
|
+
supportedDepGroups.map(
|
|
1382
|
+
async (dep) => {
|
|
1383
|
+
const { stdout } = await executeProcess({
|
|
1384
|
+
command: pkgManagerCommands[packageManager],
|
|
1385
|
+
args: getAuditCommandArgs(packageManager, dep),
|
|
1386
|
+
cwd: process.cwd(),
|
|
1387
|
+
ignoreExitCode: packageManager === "yarn-classic" || packageManager === "pnpm"
|
|
1388
|
+
// yarn v1 and PNPM do not have exit code configuration
|
|
1389
|
+
});
|
|
1390
|
+
return [dep, normalizeAuditMapper[packageManager](stdout)];
|
|
1391
|
+
}
|
|
1392
|
+
)
|
|
1021
1393
|
);
|
|
1022
1394
|
const rejected = auditResults.filter(isPromiseRejectedResult);
|
|
1023
1395
|
if (rejected.length > 0) {
|
|
1024
1396
|
rejected.map((result) => {
|
|
1025
1397
|
console.error(result.reason);
|
|
1026
1398
|
});
|
|
1027
|
-
throw new Error(
|
|
1399
|
+
throw new Error(
|
|
1400
|
+
`JS Packages plugin: Running ${pkgManagerCommands[packageManager]} audit failed.`
|
|
1401
|
+
);
|
|
1028
1402
|
}
|
|
1029
|
-
|
|
1403
|
+
const fulfilled = objectFromEntries(
|
|
1404
|
+
auditResults.filter(isPromiseFulfilledResult).map((x) => x.value)
|
|
1405
|
+
);
|
|
1406
|
+
const uniqueResults = postProcessingAuditMapper[packageManager]?.(fulfilled) ?? fulfilled;
|
|
1407
|
+
return supportedDepGroups.map(
|
|
1408
|
+
(group) => auditResultToAuditOutput(
|
|
1409
|
+
uniqueResults[group],
|
|
1410
|
+
packageManager,
|
|
1411
|
+
group,
|
|
1412
|
+
auditLevelMapping
|
|
1413
|
+
)
|
|
1414
|
+
);
|
|
1030
1415
|
}
|
|
1031
|
-
function
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1416
|
+
function getAuditCommandArgs(packageManager, group) {
|
|
1417
|
+
return [
|
|
1418
|
+
...packageManager === "yarn-modern" ? ["npm"] : [],
|
|
1419
|
+
"audit",
|
|
1420
|
+
"--json",
|
|
1421
|
+
...auditArgs(group)[packageManager]
|
|
1035
1422
|
];
|
|
1036
|
-
return [...flags, "--json", "--audit-level=none"];
|
|
1037
1423
|
}
|
|
1038
1424
|
|
|
1039
1425
|
// packages/plugin-js-packages/src/bin.ts
|
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.
|
|
7
|
+
var version = "0.34.0";
|
|
8
8
|
|
|
9
9
|
// packages/plugin-js-packages/src/lib/config.ts
|
|
10
10
|
import { z as z15 } from "zod";
|
|
@@ -834,9 +834,9 @@ async function jsPackagesPlugin(config) {
|
|
|
834
834
|
);
|
|
835
835
|
return {
|
|
836
836
|
slug: "js-packages",
|
|
837
|
-
title: "
|
|
837
|
+
title: "JS Packages",
|
|
838
838
|
icon: pkgManagerIcons[pkgManager],
|
|
839
|
-
description: "This plugin runs audit to uncover vulnerabilities and lists outdated dependencies. It supports npm, yarn classic
|
|
839
|
+
description: "This plugin runs audit to uncover vulnerabilities and lists outdated dependencies. It supports npm, yarn classic, yarn modern, and pnpm package managers.",
|
|
840
840
|
docsUrl: pkgManagerDocs[pkgManager],
|
|
841
841
|
packageName: name,
|
|
842
842
|
version,
|
|
@@ -854,9 +854,15 @@ function createGroups(pkgManager, checks) {
|
|
|
854
854
|
docsUrl: auditDocs[pkgManager],
|
|
855
855
|
refs: [
|
|
856
856
|
// eslint-disable-next-line no-magic-numbers
|
|
857
|
-
{ slug: `${pkgManager}-audit-prod`, weight:
|
|
857
|
+
{ slug: `${pkgManager}-audit-prod`, weight: 3 },
|
|
858
858
|
{ slug: `${pkgManager}-audit-dev`, weight: 1 },
|
|
859
|
-
|
|
859
|
+
// Yarn v2 does not support audit for optional dependencies
|
|
860
|
+
...pkgManager === "yarn-modern" ? [] : [
|
|
861
|
+
{
|
|
862
|
+
slug: `${pkgManager}-audit-optional`,
|
|
863
|
+
weight: 1
|
|
864
|
+
}
|
|
865
|
+
]
|
|
860
866
|
]
|
|
861
867
|
},
|
|
862
868
|
outdated: {
|
|
@@ -866,7 +872,7 @@ function createGroups(pkgManager, checks) {
|
|
|
866
872
|
docsUrl: outdatedDocs[pkgManager],
|
|
867
873
|
refs: [
|
|
868
874
|
// eslint-disable-next-line no-magic-numbers
|
|
869
|
-
{ slug: `${pkgManager}-outdated-prod`, weight:
|
|
875
|
+
{ slug: `${pkgManager}-outdated-prod`, weight: 3 },
|
|
870
876
|
{ slug: `${pkgManager}-outdated-dev`, weight: 1 },
|
|
871
877
|
{ slug: `${pkgManager}-outdated-optional`, weight: 1 }
|
|
872
878
|
]
|
|
@@ -888,12 +894,15 @@ function createAudits(pkgManager, checks) {
|
|
|
888
894
|
description: getAuditDescription(check, "dev"),
|
|
889
895
|
docsUrl: dependencyDocs.dev
|
|
890
896
|
},
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
+
// Yarn v2 does not support audit for optional dependencies
|
|
898
|
+
...pkgManager === "yarn-modern" && check === "audit" ? [] : [
|
|
899
|
+
{
|
|
900
|
+
slug: `${pkgManager}-${check}-optional`,
|
|
901
|
+
title: getAuditTitle(pkgManager, check, "optional"),
|
|
902
|
+
description: getAuditDescription(check, "optional"),
|
|
903
|
+
docsUrl: dependencyDocs.optional
|
|
904
|
+
}
|
|
905
|
+
]
|
|
897
906
|
]);
|
|
898
907
|
}
|
|
899
908
|
function getAuditTitle(pkgManager, check, dependencyType) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-pushup/js-packages-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"@code-pushup/models": "
|
|
6
|
-
"@code-pushup/utils": "
|
|
5
|
+
"@code-pushup/models": "0.34.0",
|
|
6
|
+
"@code-pushup/utils": "0.34.0",
|
|
7
7
|
"zod": "^3.22.4"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
package/src/lib/config.d.ts
CHANGED
|
@@ -9,15 +9,16 @@ export type PackageManager = z.infer<typeof packageManagerSchema>;
|
|
|
9
9
|
export declare const packageAuditLevels: readonly ["critical", "high", "moderate", "low", "info"];
|
|
10
10
|
declare const packageAuditLevelSchema: z.ZodEnum<["critical", "high", "moderate", "low", "info"]>;
|
|
11
11
|
export type PackageAuditLevel = z.infer<typeof packageAuditLevelSchema>;
|
|
12
|
-
export
|
|
12
|
+
export type AuditSeverity = Record<PackageAuditLevel, IssueSeverity>;
|
|
13
|
+
export declare function fillAuditLevelMapping(mapping: Partial<AuditSeverity>): AuditSeverity;
|
|
13
14
|
export declare const jsPackagesPluginConfigSchema: z.ZodObject<{
|
|
14
15
|
checks: z.ZodDefault<z.ZodArray<z.ZodEnum<["audit", "outdated"]>, "many">>;
|
|
15
16
|
packageManager: z.ZodEnum<["npm", "yarn-classic", "yarn-modern", "pnpm"]>;
|
|
16
|
-
auditLevelMapping: z.ZodEffects<z.ZodDefault<z.ZodRecord<z.ZodEnum<["critical", "high", "moderate", "low", "info"]>, z.ZodEnum<["info", "warning", "error"]>>>,
|
|
17
|
+
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>;
|
|
17
18
|
}, "strip", z.ZodTypeAny, {
|
|
18
19
|
checks: ("audit" | "outdated")[];
|
|
19
20
|
packageManager: "npm" | "pnpm" | "yarn-classic" | "yarn-modern";
|
|
20
|
-
auditLevelMapping:
|
|
21
|
+
auditLevelMapping: AuditSeverity;
|
|
21
22
|
}, {
|
|
22
23
|
packageManager: "npm" | "pnpm" | "yarn-classic" | "yarn-modern";
|
|
23
24
|
checks?: ("audit" | "outdated")[] | undefined;
|
package/src/lib/constants.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { IssueSeverity, MaterialIcon } from '@code-pushup/models';
|
|
2
2
|
import type { DependencyGroup, PackageAuditLevel, PackageManager } from './config';
|
|
3
|
+
import { DependencyGroupLong } from './runner/outdated/types';
|
|
3
4
|
export declare const defaultAuditLevelMapping: Record<PackageAuditLevel, IssueSeverity>;
|
|
5
|
+
export declare const dependencyGroupToLong: Record<DependencyGroup, DependencyGroupLong>;
|
|
6
|
+
export declare const pkgManagerCommands: Record<PackageManager, string>;
|
|
4
7
|
export declare const pkgManagerNames: Record<PackageManager, string>;
|
|
5
8
|
export declare const pkgManagerIcons: Record<PackageManager, MaterialIcon>;
|
|
6
9
|
export declare const pkgManagerDocs: Record<PackageManager, string>;
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import { PackageAuditLevel } from '../../config';
|
|
1
|
+
import { DependencyGroup, PackageAuditLevel, PackageManager } from '../../config';
|
|
2
|
+
import { AuditResult } from './types';
|
|
2
3
|
export declare const auditScoreModifiers: Record<PackageAuditLevel, number>;
|
|
4
|
+
export declare const normalizeAuditMapper: Record<PackageManager, (output: string) => AuditResult>;
|
|
5
|
+
export declare const postProcessingAuditMapper: Partial<Record<PackageManager, (result: Record<DependencyGroup, AuditResult>) => Record<DependencyGroup, AuditResult>>>;
|
|
6
|
+
export declare const auditArgs: (groupDep: DependencyGroup) => Record<PackageManager, string[]>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AuditOutput, Issue
|
|
2
|
-
import { DependencyGroup,
|
|
3
|
-
import {
|
|
4
|
-
export declare function auditResultToAuditOutput(result:
|
|
5
|
-
export declare function calculateAuditScore(stats:
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function vulnerabilitiesToIssues(vulnerabilities:
|
|
1
|
+
import type { AuditOutput, Issue } from '@code-pushup/models';
|
|
2
|
+
import { AuditSeverity, DependencyGroup, PackageManager } from '../../config';
|
|
3
|
+
import { AuditResult, AuditSummary, Vulnerability } from './types';
|
|
4
|
+
export declare function auditResultToAuditOutput(result: AuditResult, packageManager: PackageManager, dependenciesType: DependencyGroup, auditLevelMapping: AuditSeverity): AuditOutput;
|
|
5
|
+
export declare function calculateAuditScore(stats: AuditSummary): number;
|
|
6
|
+
export declare function summaryToDisplayValue(summary: AuditSummary): string;
|
|
7
|
+
export declare function vulnerabilitiesToIssues(vulnerabilities: Vulnerability[], auditLevelMapping: AuditSeverity): Issue[];
|
|
@@ -1,27 +1,103 @@
|
|
|
1
1
|
import type { PackageAuditLevel } from '../../config';
|
|
2
|
-
type
|
|
2
|
+
export type Vulnerability = {
|
|
3
|
+
name: string;
|
|
4
|
+
id?: number;
|
|
5
|
+
title?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
severity: PackageAuditLevel;
|
|
8
|
+
versionRange: string;
|
|
9
|
+
directDependency: string | true;
|
|
10
|
+
fixInformation: string | false;
|
|
11
|
+
};
|
|
12
|
+
export type AuditSummary = Record<PackageAuditLevel | 'total', number>;
|
|
13
|
+
export type AuditResult = {
|
|
14
|
+
vulnerabilities: Vulnerability[];
|
|
15
|
+
summary: AuditSummary;
|
|
16
|
+
};
|
|
17
|
+
export type NpmAdvisory = {
|
|
3
18
|
title: string;
|
|
4
19
|
url: string;
|
|
5
20
|
};
|
|
6
|
-
type
|
|
21
|
+
export type NpmFixInformation = {
|
|
7
22
|
name: string;
|
|
8
23
|
version: string;
|
|
9
24
|
isSemVerMajor: boolean;
|
|
10
25
|
};
|
|
11
|
-
export type
|
|
26
|
+
export type NpmVulnerability = {
|
|
12
27
|
name: string;
|
|
13
28
|
severity: PackageAuditLevel;
|
|
14
|
-
|
|
29
|
+
isDirect: boolean;
|
|
30
|
+
effects: string[];
|
|
31
|
+
via: NpmAdvisory[] | string[];
|
|
15
32
|
range: string;
|
|
16
|
-
fixAvailable: boolean |
|
|
17
|
-
};
|
|
18
|
-
export type Vulnerabilities = {
|
|
19
|
-
[key: string]: Vulnerability;
|
|
33
|
+
fixAvailable: boolean | NpmFixInformation;
|
|
20
34
|
};
|
|
35
|
+
export type NpmVulnerabilities = Record<string, NpmVulnerability>;
|
|
21
36
|
export type NpmAuditResultJson = {
|
|
22
|
-
vulnerabilities:
|
|
37
|
+
vulnerabilities: NpmVulnerabilities;
|
|
38
|
+
metadata: {
|
|
39
|
+
vulnerabilities: AuditSummary;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type Yarnv1AuditAdvisory = {
|
|
43
|
+
type: 'auditAdvisory';
|
|
44
|
+
data: {
|
|
45
|
+
resolution: {
|
|
46
|
+
id: number;
|
|
47
|
+
path: string;
|
|
48
|
+
};
|
|
49
|
+
advisory: {
|
|
50
|
+
module_name: string;
|
|
51
|
+
severity: PackageAuditLevel;
|
|
52
|
+
vulnerable_versions: string;
|
|
53
|
+
recommendation: string;
|
|
54
|
+
title: string;
|
|
55
|
+
url: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type Yarnv1AuditSummary = {
|
|
60
|
+
type: 'auditSummary';
|
|
61
|
+
data: {
|
|
62
|
+
vulnerabilities: Record<PackageAuditLevel, number>;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export type Yarnv1AuditResultJson = [
|
|
66
|
+
...Yarnv1AuditAdvisory[],
|
|
67
|
+
Yarnv1AuditSummary
|
|
68
|
+
];
|
|
69
|
+
export type Yarnv2AuditAdvisory = {
|
|
70
|
+
module_name: string;
|
|
71
|
+
severity: PackageAuditLevel;
|
|
72
|
+
vulnerable_versions: string;
|
|
73
|
+
recommendation: string;
|
|
74
|
+
title: string;
|
|
75
|
+
url: string;
|
|
76
|
+
findings: {
|
|
77
|
+
paths: string[];
|
|
78
|
+
}[];
|
|
79
|
+
};
|
|
80
|
+
export type Yarnv2AuditResultJson = {
|
|
81
|
+
advisories: Record<string, Yarnv2AuditAdvisory>;
|
|
82
|
+
metadata: {
|
|
83
|
+
vulnerabilities: Record<PackageAuditLevel, number>;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
export type PnpmAuditAdvisory = {
|
|
87
|
+
module_name: string;
|
|
88
|
+
id: number;
|
|
89
|
+
severity: PackageAuditLevel;
|
|
90
|
+
vulnerable_versions: string;
|
|
91
|
+
recommendation: string;
|
|
92
|
+
title: string;
|
|
93
|
+
url: string;
|
|
94
|
+
findings: {
|
|
95
|
+
paths: string[];
|
|
96
|
+
}[];
|
|
97
|
+
};
|
|
98
|
+
export type PnpmAuditResultJson = {
|
|
99
|
+
advisories: Record<string, PnpmAuditAdvisory>;
|
|
23
100
|
metadata: {
|
|
24
|
-
vulnerabilities: Record<PackageAuditLevel
|
|
101
|
+
vulnerabilities: Record<PackageAuditLevel, number>;
|
|
25
102
|
};
|
|
26
103
|
};
|
|
27
|
-
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AuditResult, NpmAdvisory, NpmFixInformation, NpmVulnerabilities } from './types';
|
|
2
|
+
export declare function npmToAuditResult(output: string): AuditResult;
|
|
3
|
+
export declare function npmToFixInformation(fixAvailable: boolean | NpmFixInformation): string;
|
|
4
|
+
export declare function npmToAdvisory(name: string, vulnerabilities: NpmVulnerabilities, prevNodes?: Set<string>): NpmAdvisory | null;
|
|
5
|
+
export declare function yarnv1ToAuditResult(output: string): AuditResult;
|
|
6
|
+
export declare function yarnv2ToAuditResult(output: string): AuditResult;
|
|
7
|
+
export declare function pnpmToAuditResult(output: string): AuditResult;
|
|
8
|
+
export declare function pnpmToDirectDependency(path: string): string | true;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { IssueSeverity } from '@code-pushup/models';
|
|
2
|
-
import {
|
|
2
|
+
import { PackageManager } from '../../config';
|
|
3
|
+
import { OutdatedResult, VersionType } from './types';
|
|
3
4
|
export declare const outdatedSeverity: Record<VersionType, IssueSeverity>;
|
|
5
|
+
export declare const normalizeOutdatedMapper: Record<PackageManager, (output: string) => OutdatedResult>;
|
|
6
|
+
export declare const outdatedArgs: Record<PackageManager, string[]>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Issue } from '@code-pushup/models';
|
|
2
|
-
import { DependencyGroup } from '../../config';
|
|
3
|
-
import {
|
|
4
|
-
export declare function outdatedResultToAuditOutput(result:
|
|
2
|
+
import { DependencyGroup, PackageManager } from '../../config';
|
|
3
|
+
import { OutdatedResult, PackageVersion, VersionType } from './types';
|
|
4
|
+
export declare function outdatedResultToAuditOutput(result: OutdatedResult, packageManager: PackageManager, dependencyGroup: DependencyGroup): {
|
|
5
5
|
details?: {
|
|
6
6
|
issues: {
|
|
7
7
|
message: string;
|
|
@@ -23,7 +23,7 @@ export declare function outdatedResultToAuditOutput(result: NpmOutdatedResultJso
|
|
|
23
23
|
displayValue: string;
|
|
24
24
|
};
|
|
25
25
|
export declare function calculateOutdatedScore(majorOutdated: number, totalDeps: number): number;
|
|
26
|
-
export declare function outdatedToDisplayValue(
|
|
27
|
-
export declare function outdatedToIssues(dependencies:
|
|
28
|
-
export declare function getOutdatedLevel(currentFullVersion: string,
|
|
26
|
+
export declare function outdatedToDisplayValue(stats: Record<VersionType, number>): string;
|
|
27
|
+
export declare function outdatedToIssues(dependencies: OutdatedResult): Issue[];
|
|
28
|
+
export declare function getOutdatedLevel(currentFullVersion: string, latestFullVersion: string): VersionType;
|
|
29
29
|
export declare function splitPackageVersion(fullVersion: string): PackageVersion;
|
|
@@ -1,15 +1,54 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const versionType: readonly ["major", "minor", "patch"];
|
|
2
|
+
export type VersionType = (typeof versionType)[number];
|
|
2
3
|
export type PackageVersion = Record<VersionType, number>;
|
|
3
|
-
export type
|
|
4
|
+
export type DependencyGroupLong = 'dependencies' | 'devDependencies' | 'optionalDependencies';
|
|
5
|
+
export type OutdatedResult = {
|
|
6
|
+
name: string;
|
|
7
|
+
current: string;
|
|
8
|
+
latest: string;
|
|
9
|
+
type: DependencyGroupLong;
|
|
10
|
+
url?: string;
|
|
11
|
+
}[];
|
|
12
|
+
export type NpmVersionOverview = {
|
|
4
13
|
current?: string;
|
|
5
|
-
|
|
6
|
-
type:
|
|
14
|
+
latest: string;
|
|
15
|
+
type: DependencyGroupLong;
|
|
7
16
|
homepage?: string;
|
|
8
17
|
};
|
|
9
|
-
export type
|
|
18
|
+
export type NpmNormalizedOverview = Omit<NpmVersionOverview, 'current'> & {
|
|
19
|
+
current: string;
|
|
20
|
+
};
|
|
21
|
+
export type NpmOutdatedResultJson = Record<string, NpmVersionOverview>;
|
|
22
|
+
export type Yarnv1VersionOverview = [
|
|
23
|
+
string,
|
|
24
|
+
string,
|
|
25
|
+
string,
|
|
26
|
+
string,
|
|
27
|
+
string,
|
|
28
|
+
DependencyGroupLong,
|
|
29
|
+
string
|
|
30
|
+
];
|
|
31
|
+
type Yarnv1Info = {
|
|
32
|
+
type: 'info';
|
|
33
|
+
};
|
|
34
|
+
type Yarnv1Table = {
|
|
35
|
+
type: 'table';
|
|
36
|
+
data: {
|
|
37
|
+
body: Yarnv1VersionOverview[];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export type Yarnv1OutdatedResultJson = [Yarnv1Info, Yarnv1Table];
|
|
41
|
+
export type Yarnv2VersionOverview = {
|
|
10
42
|
current: string;
|
|
43
|
+
latest: string;
|
|
44
|
+
name: string;
|
|
45
|
+
type: DependencyGroupLong;
|
|
11
46
|
};
|
|
12
|
-
export type
|
|
13
|
-
export type
|
|
14
|
-
|
|
47
|
+
export type Yarnv2OutdatedResultJson = Yarnv2VersionOverview[];
|
|
48
|
+
export type PnpmVersionOverview = {
|
|
49
|
+
current: string;
|
|
50
|
+
latest: string;
|
|
51
|
+
dependencyType: DependencyGroupLong;
|
|
15
52
|
};
|
|
53
|
+
export type PnpmOutdatedResultJson = Record<string, PnpmVersionOverview>;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { OutdatedResult } from './types';
|
|
2
|
+
export declare function npmToOutdatedResult(output: string): OutdatedResult;
|
|
3
|
+
export declare function yarnv1ToOutdatedResult(output: string): OutdatedResult;
|
|
4
|
+
export declare function yarnv2ToOutdatedResult(output: string): OutdatedResult;
|
|
5
|
+
export declare function pnpmToOutdatedResult(output: string): OutdatedResult;
|