@code-pushup/js-packages-plugin 0.29.0 → 0.30.0-alpha
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 +393 -75
- package/index.js +20 -11
- package/package.json +1 -1
- package/src/lib/config.d.ts +4 -3
- package/src/lib/constants.d.ts +3 -0
- package/src/lib/runner/audit/constants.d.ts +4 -1
- package/src/lib/runner/audit/transform.d.ts +7 -7
- package/src/lib/runner/audit/types.d.ts +69 -11
- package/src/lib/runner/audit/unify-type.d.ts +6 -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 +41 -8
- package/src/lib/runner/outdated/unify-type.d.ts +4 -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,173 @@ 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
|
+
const total = Object.values(yarnv2Audit.metadata.vulnerabilities).reduce(
|
|
1038
|
+
(acc, value) => acc + value,
|
|
1039
|
+
0
|
|
1040
|
+
);
|
|
1041
|
+
const summary = { ...yarnv2Audit.metadata.vulnerabilities, total };
|
|
1042
|
+
return { vulnerabilities, summary };
|
|
1043
|
+
}
|
|
1044
|
+
|
|
837
1045
|
// packages/plugin-js-packages/src/lib/runner/audit/constants.ts
|
|
838
1046
|
var auditScoreModifiers = {
|
|
839
1047
|
critical: 1,
|
|
@@ -842,20 +1050,47 @@ var auditScoreModifiers = {
|
|
|
842
1050
|
low: 0.02,
|
|
843
1051
|
info: 0.01
|
|
844
1052
|
};
|
|
1053
|
+
var normalizeAuditMapper = {
|
|
1054
|
+
npm: npmToAuditResult,
|
|
1055
|
+
"yarn-classic": yarnv1ToAuditResult,
|
|
1056
|
+
"yarn-modern": yarnv2ToAuditResult,
|
|
1057
|
+
pnpm: () => {
|
|
1058
|
+
throw new Error("PNPM audit is not supported yet.");
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
var npmDependencyOptions = {
|
|
1062
|
+
prod: ["--omit=dev", "--omit=optional"],
|
|
1063
|
+
dev: ["--include=dev", "--omit=optional"],
|
|
1064
|
+
optional: ["--include=optional", "--omit=dev"]
|
|
1065
|
+
};
|
|
1066
|
+
var yarnv2EnvironmentOptions = {
|
|
1067
|
+
prod: "production",
|
|
1068
|
+
dev: "development",
|
|
1069
|
+
optional: ""
|
|
1070
|
+
};
|
|
1071
|
+
var auditArgs = (groupDep) => ({
|
|
1072
|
+
npm: [...npmDependencyOptions[groupDep], "--json", "--audit-level=none"],
|
|
1073
|
+
"yarn-classic": ["--json", "--groups", dependencyGroupToLong[groupDep]],
|
|
1074
|
+
"yarn-modern": [
|
|
1075
|
+
"--json",
|
|
1076
|
+
"--environment",
|
|
1077
|
+
yarnv2EnvironmentOptions[groupDep]
|
|
1078
|
+
],
|
|
1079
|
+
// TODO: Add once PNPM is supported.
|
|
1080
|
+
pnpm: []
|
|
1081
|
+
});
|
|
845
1082
|
|
|
846
1083
|
// packages/plugin-js-packages/src/lib/runner/audit/transform.ts
|
|
847
|
-
function auditResultToAuditOutput(result, dependenciesType, auditLevelMapping) {
|
|
1084
|
+
function auditResultToAuditOutput(result, packageManager, dependenciesType, auditLevelMapping) {
|
|
848
1085
|
const issues = vulnerabilitiesToIssues(
|
|
849
1086
|
result.vulnerabilities,
|
|
850
1087
|
auditLevelMapping
|
|
851
1088
|
);
|
|
852
1089
|
return {
|
|
853
|
-
slug:
|
|
854
|
-
score: calculateAuditScore(result.
|
|
855
|
-
value: result.
|
|
856
|
-
displayValue:
|
|
857
|
-
result.metadata.vulnerabilities
|
|
858
|
-
),
|
|
1090
|
+
slug: `${packageManager}-audit-${dependenciesType}`,
|
|
1091
|
+
score: calculateAuditScore(result.summary),
|
|
1092
|
+
value: result.summary.total,
|
|
1093
|
+
displayValue: summaryToDisplayValue(result.summary),
|
|
859
1094
|
...issues.length > 0 && { details: { issues } }
|
|
860
1095
|
};
|
|
861
1096
|
}
|
|
@@ -874,31 +1109,26 @@ function calculateAuditScore(stats) {
|
|
|
874
1109
|
1
|
|
875
1110
|
);
|
|
876
1111
|
}
|
|
877
|
-
function
|
|
878
|
-
if (
|
|
1112
|
+
function summaryToDisplayValue(summary) {
|
|
1113
|
+
if (summary.total === 0) {
|
|
879
1114
|
return "0 vulnerabilities";
|
|
880
1115
|
}
|
|
881
|
-
const vulnerabilityStats = packageAuditLevels.map(
|
|
882
|
-
|
|
883
|
-
).filter((text) => text !== "").join(", ");
|
|
884
|
-
return `${vulnerabilities.total} ${vulnerabilities.total === 1 ? "vulnerability" : "vulnerabilities"} (${vulnerabilityStats})`;
|
|
1116
|
+
const vulnerabilityStats = packageAuditLevels.map((level) => summary[level] > 0 ? `${summary[level]} ${level}` : "").filter((text) => text !== "").join(", ");
|
|
1117
|
+
return `${summary.total} ${summary.total === 1 ? "vulnerability" : "vulnerabilities"} (${vulnerabilityStats})`;
|
|
885
1118
|
}
|
|
886
1119
|
function vulnerabilitiesToIssues(vulnerabilities, auditLevelMapping) {
|
|
887
|
-
if (
|
|
1120
|
+
if (vulnerabilities.length === 0) {
|
|
888
1121
|
return [];
|
|
889
1122
|
}
|
|
890
|
-
return
|
|
891
|
-
const versionRange = detail.
|
|
892
|
-
const
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
severity: auditLevelMapping[detail.severity]
|
|
898
|
-
};
|
|
899
|
-
}
|
|
1123
|
+
return vulnerabilities.map((detail) => {
|
|
1124
|
+
const versionRange = detail.versionRange === "*" ? "**all** versions" : `versions **${detail.versionRange}**`;
|
|
1125
|
+
const directDependency = typeof detail.directDependency === "string" ? `\`${detail.directDependency}\`` : "";
|
|
1126
|
+
const depHierarchy = directDependency === "" ? `\`${detail.name}\` dependency` : `${apostrophize(directDependency)} dependency \`${detail.name}\``;
|
|
1127
|
+
const vulnerabilitySummary = `has a **${detail.severity}** vulnerability in ${versionRange}.`;
|
|
1128
|
+
const fixInfo = detail.fixInformation ? ` ${detail.fixInformation}` : "";
|
|
1129
|
+
const additionalInfo = detail.title != null && detail.url != null ? ` More information: [${detail.title}](${detail.url})` : "";
|
|
900
1130
|
return {
|
|
901
|
-
message: `${
|
|
1131
|
+
message: `${depHierarchy} ${vulnerabilitySummary}${fixInfo}${additionalInfo}`,
|
|
902
1132
|
severity: auditLevelMapping[detail.severity]
|
|
903
1133
|
};
|
|
904
1134
|
});
|
|
@@ -914,67 +1144,129 @@ var PLUGIN_CONFIG_PATH = join2(
|
|
|
914
1144
|
"plugin-config.json"
|
|
915
1145
|
);
|
|
916
1146
|
|
|
1147
|
+
// packages/plugin-js-packages/src/lib/runner/outdated/unify-type.ts
|
|
1148
|
+
function npmToOutdatedResult(output) {
|
|
1149
|
+
const npmOutdated = JSON.parse(output);
|
|
1150
|
+
return objectToEntries(npmOutdated).filter(
|
|
1151
|
+
(entry) => entry[1].current != null
|
|
1152
|
+
).map(([name, overview]) => ({
|
|
1153
|
+
name,
|
|
1154
|
+
current: overview.current,
|
|
1155
|
+
latest: overview.latest,
|
|
1156
|
+
type: overview.type,
|
|
1157
|
+
...overview.homepage != null && { url: overview.homepage }
|
|
1158
|
+
}));
|
|
1159
|
+
}
|
|
1160
|
+
function yarnv1ToOutdatedResult(output) {
|
|
1161
|
+
const yarnv1Outdated = fromJsonLines(output);
|
|
1162
|
+
const dependencies = yarnv1Outdated[1].data.body;
|
|
1163
|
+
return dependencies.map(([name, current, _, latest, __, type, url]) => ({
|
|
1164
|
+
name,
|
|
1165
|
+
current,
|
|
1166
|
+
latest,
|
|
1167
|
+
type,
|
|
1168
|
+
url
|
|
1169
|
+
}));
|
|
1170
|
+
}
|
|
1171
|
+
function yarnv2ToOutdatedResult(output) {
|
|
1172
|
+
const npmOutdated = JSON.parse(output);
|
|
1173
|
+
return npmOutdated.map(({ name, current, latest, type }) => ({
|
|
1174
|
+
name,
|
|
1175
|
+
current,
|
|
1176
|
+
latest,
|
|
1177
|
+
type
|
|
1178
|
+
}));
|
|
1179
|
+
}
|
|
1180
|
+
|
|
917
1181
|
// packages/plugin-js-packages/src/lib/runner/outdated/constants.ts
|
|
918
1182
|
var outdatedSeverity = {
|
|
919
1183
|
major: "error",
|
|
920
1184
|
minor: "warning",
|
|
921
1185
|
patch: "info"
|
|
922
1186
|
};
|
|
1187
|
+
var outdatedArgs = {
|
|
1188
|
+
npm: ["--json", "--long"],
|
|
1189
|
+
"yarn-classic": ["--json"],
|
|
1190
|
+
"yarn-modern": ["--json"],
|
|
1191
|
+
pnpm: []
|
|
1192
|
+
};
|
|
1193
|
+
var normalizeOutdatedMapper = {
|
|
1194
|
+
npm: npmToOutdatedResult,
|
|
1195
|
+
"yarn-classic": yarnv1ToOutdatedResult,
|
|
1196
|
+
"yarn-modern": yarnv2ToOutdatedResult,
|
|
1197
|
+
pnpm: (_) => []
|
|
1198
|
+
};
|
|
1199
|
+
|
|
1200
|
+
// packages/plugin-js-packages/src/lib/runner/outdated/types.ts
|
|
1201
|
+
var versionType = ["major", "minor", "patch"];
|
|
923
1202
|
|
|
924
1203
|
// packages/plugin-js-packages/src/lib/runner/outdated/transform.ts
|
|
925
|
-
function outdatedResultToAuditOutput(result,
|
|
926
|
-
const
|
|
927
|
-
(
|
|
928
|
-
).filter(
|
|
929
|
-
([, detail]) => dependenciesType === "prod" ? detail.type === "dependencies" : detail.type === `${dependenciesType}Dependencies`
|
|
1204
|
+
function outdatedResultToAuditOutput(result, packageManager, dependencyGroup) {
|
|
1205
|
+
const relevantDependencies = result.filter(
|
|
1206
|
+
(dep) => dep.type === dependencyGroupToLong[dependencyGroup]
|
|
930
1207
|
);
|
|
931
|
-
const outdatedDependencies =
|
|
932
|
-
(
|
|
1208
|
+
const outdatedDependencies = relevantDependencies.filter(
|
|
1209
|
+
(dep) => dep.current !== dep.latest
|
|
1210
|
+
);
|
|
1211
|
+
const outdatedStats = outdatedDependencies.reduce(
|
|
1212
|
+
(acc, dep) => {
|
|
1213
|
+
const outdatedLevel = getOutdatedLevel(dep.current, dep.latest);
|
|
1214
|
+
return { ...acc, [outdatedLevel]: acc[outdatedLevel] + 1 };
|
|
1215
|
+
},
|
|
1216
|
+
{ major: 0, minor: 0, patch: 0 }
|
|
933
1217
|
);
|
|
934
|
-
const majorOutdatedAmount = outdatedDependencies.filter(
|
|
935
|
-
([, versions]) => getOutdatedLevel(versions.current, versions.wanted) === "major"
|
|
936
|
-
).length;
|
|
937
1218
|
const issues = outdatedDependencies.length === 0 ? [] : outdatedToIssues(outdatedDependencies);
|
|
938
1219
|
return {
|
|
939
|
-
slug:
|
|
1220
|
+
slug: `${packageManager}-outdated-${dependencyGroup}`,
|
|
940
1221
|
score: calculateOutdatedScore(
|
|
941
|
-
|
|
942
|
-
|
|
1222
|
+
outdatedStats.major,
|
|
1223
|
+
relevantDependencies.length
|
|
943
1224
|
),
|
|
944
1225
|
value: outdatedDependencies.length,
|
|
945
|
-
displayValue: outdatedToDisplayValue(
|
|
946
|
-
majorOutdatedAmount,
|
|
947
|
-
outdatedDependencies.length
|
|
948
|
-
),
|
|
1226
|
+
displayValue: outdatedToDisplayValue(outdatedStats),
|
|
949
1227
|
...issues.length > 0 && { details: { issues } }
|
|
950
1228
|
};
|
|
951
1229
|
}
|
|
952
1230
|
function calculateOutdatedScore(majorOutdated, totalDeps) {
|
|
953
1231
|
return totalDeps > 0 ? (totalDeps - majorOutdated) / totalDeps : 1;
|
|
954
1232
|
}
|
|
955
|
-
function outdatedToDisplayValue(
|
|
956
|
-
|
|
1233
|
+
function outdatedToDisplayValue(stats) {
|
|
1234
|
+
const total = stats.major + stats.minor + stats.patch;
|
|
1235
|
+
const versionBreakdown = versionType.map((version) => stats[version] > 0 ? `${stats[version]} ${version}` : "").filter((text) => text !== "");
|
|
1236
|
+
if (versionBreakdown.length === 0) {
|
|
1237
|
+
return "all dependencies are up to date";
|
|
1238
|
+
}
|
|
1239
|
+
if (versionBreakdown.length > 1) {
|
|
1240
|
+
return `${total} outdated package versions (${versionBreakdown.join(
|
|
1241
|
+
", "
|
|
1242
|
+
)})`;
|
|
1243
|
+
}
|
|
1244
|
+
return `${versionBreakdown[0]} outdated package ${pluralize(
|
|
1245
|
+
"version",
|
|
1246
|
+
total
|
|
1247
|
+
)}`;
|
|
957
1248
|
}
|
|
958
1249
|
function outdatedToIssues(dependencies) {
|
|
959
|
-
return dependencies.map((
|
|
960
|
-
const
|
|
961
|
-
const
|
|
1250
|
+
return dependencies.map((dep) => {
|
|
1251
|
+
const { name, current, latest, url } = dep;
|
|
1252
|
+
const outdatedLevel = getOutdatedLevel(current, latest);
|
|
1253
|
+
const packageReference = url == null ? `\`${name}\`` : `[\`${name}\`](${url})`;
|
|
962
1254
|
return {
|
|
963
|
-
message: `Package ${packageReference} requires a **${outdatedLevel}** update from **${
|
|
1255
|
+
message: `Package ${packageReference} requires a **${outdatedLevel}** update from **${current}** to **${latest}**.`,
|
|
964
1256
|
severity: outdatedSeverity[outdatedLevel]
|
|
965
1257
|
};
|
|
966
1258
|
});
|
|
967
1259
|
}
|
|
968
|
-
function getOutdatedLevel(currentFullVersion,
|
|
1260
|
+
function getOutdatedLevel(currentFullVersion, latestFullVersion) {
|
|
969
1261
|
const current = splitPackageVersion(currentFullVersion);
|
|
970
|
-
const
|
|
971
|
-
if (current.major <
|
|
1262
|
+
const latest = splitPackageVersion(latestFullVersion);
|
|
1263
|
+
if (current.major < latest.major) {
|
|
972
1264
|
return "major";
|
|
973
1265
|
}
|
|
974
|
-
if (current.minor <
|
|
1266
|
+
if (current.minor < latest.minor) {
|
|
975
1267
|
return "minor";
|
|
976
1268
|
}
|
|
977
|
-
if (current.patch <
|
|
1269
|
+
if (current.patch < latest.patch) {
|
|
978
1270
|
return "patch";
|
|
979
1271
|
}
|
|
980
1272
|
throw new Error("Package is not outdated.");
|
|
@@ -998,42 +1290,68 @@ async function executeRunner() {
|
|
|
998
1290
|
}
|
|
999
1291
|
async function processOutdated(packageManager) {
|
|
1000
1292
|
const { stdout } = await executeProcess({
|
|
1001
|
-
command: packageManager,
|
|
1002
|
-
args: ["outdated",
|
|
1003
|
-
|
|
1293
|
+
command: pkgManagerCommands[packageManager],
|
|
1294
|
+
args: ["outdated", ...outdatedArgs[packageManager]],
|
|
1295
|
+
cwd: process.cwd(),
|
|
1296
|
+
ignoreExitCode: true
|
|
1004
1297
|
// npm outdated returns exit code 1 when outdated dependencies are found
|
|
1005
1298
|
});
|
|
1006
|
-
const
|
|
1299
|
+
const normalizedResult = normalizeOutdatedMapper[packageManager](stdout);
|
|
1007
1300
|
return dependencyGroups.map(
|
|
1008
|
-
(dep) => outdatedResultToAuditOutput(
|
|
1301
|
+
(dep) => outdatedResultToAuditOutput(normalizedResult, packageManager, dep)
|
|
1009
1302
|
);
|
|
1010
1303
|
}
|
|
1011
1304
|
async function processAudit(packageManager, auditLevelMapping) {
|
|
1305
|
+
const supportedDepGroups = packageManager === "yarn-modern" ? dependencyGroups.filter((dep) => dep !== "optional") : dependencyGroups;
|
|
1012
1306
|
const auditResults = await Promise.allSettled(
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1307
|
+
supportedDepGroups.map(
|
|
1308
|
+
async (dep) => {
|
|
1309
|
+
const { stdout } = await executeProcess({
|
|
1310
|
+
command: pkgManagerCommands[packageManager],
|
|
1311
|
+
args: getAuditCommandArgs(packageManager, dep),
|
|
1312
|
+
cwd: process.cwd(),
|
|
1313
|
+
ignoreExitCode: packageManager === "yarn-classic"
|
|
1314
|
+
// yarn v1 does not have exit code configuration
|
|
1315
|
+
});
|
|
1316
|
+
return [dep, normalizeAuditMapper[packageManager](stdout)];
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1021
1319
|
);
|
|
1022
1320
|
const rejected = auditResults.filter(isPromiseRejectedResult);
|
|
1023
1321
|
if (rejected.length > 0) {
|
|
1024
1322
|
rejected.map((result) => {
|
|
1025
1323
|
console.error(result.reason);
|
|
1026
1324
|
});
|
|
1027
|
-
throw new Error(
|
|
1325
|
+
throw new Error(
|
|
1326
|
+
`JS Packages plugin: Running ${pkgManagerCommands[packageManager]} audit failed.`
|
|
1327
|
+
);
|
|
1028
1328
|
}
|
|
1029
|
-
|
|
1329
|
+
const fulfilled = objectFromEntries(
|
|
1330
|
+
auditResults.filter(isPromiseFulfilledResult).map((x) => x.value)
|
|
1331
|
+
);
|
|
1332
|
+
const uniqueResults = packageManager === "npm" ? filterNpmAuditResults(fulfilled) : fulfilled;
|
|
1333
|
+
return supportedDepGroups.map(
|
|
1334
|
+
(group) => auditResultToAuditOutput(
|
|
1335
|
+
uniqueResults[group],
|
|
1336
|
+
packageManager,
|
|
1337
|
+
group,
|
|
1338
|
+
auditLevelMapping
|
|
1339
|
+
)
|
|
1340
|
+
);
|
|
1030
1341
|
}
|
|
1031
|
-
function
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1342
|
+
function getAuditCommandArgs(packageManager, group) {
|
|
1343
|
+
return [
|
|
1344
|
+
...packageManager === "yarn-modern" ? ["npm"] : [],
|
|
1345
|
+
"audit",
|
|
1346
|
+
...auditArgs(group)[packageManager]
|
|
1035
1347
|
];
|
|
1036
|
-
|
|
1348
|
+
}
|
|
1349
|
+
function filterNpmAuditResults(results) {
|
|
1350
|
+
return {
|
|
1351
|
+
prod: results.prod,
|
|
1352
|
+
dev: filterAuditResult(results.dev, "name", results.prod),
|
|
1353
|
+
optional: filterAuditResult(results.optional, "name", results.prod)
|
|
1354
|
+
};
|
|
1037
1355
|
}
|
|
1038
1356
|
|
|
1039
1357
|
// packages/plugin-js-packages/src/bin.ts
|
package/index.js
CHANGED
|
@@ -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
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,5 @@
|
|
|
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 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,85 @@
|
|
|
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>;
|
|
23
82
|
metadata: {
|
|
24
|
-
vulnerabilities: Record<PackageAuditLevel
|
|
83
|
+
vulnerabilities: Record<PackageAuditLevel, number>;
|
|
25
84
|
};
|
|
26
85
|
};
|
|
27
|
-
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
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;
|
|
@@ -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 outdatedArgs: Record<PackageManager, string[]>;
|
|
6
|
+
export declare const normalizeOutdatedMapper: Record<PackageManager, (output: string) => OutdatedResult>;
|
|
@@ -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,48 @@
|
|
|
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'> & {
|
|
10
19
|
current: string;
|
|
11
20
|
};
|
|
12
|
-
export type
|
|
13
|
-
export type
|
|
14
|
-
|
|
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 = {
|
|
42
|
+
current: string;
|
|
43
|
+
latest: string;
|
|
44
|
+
name: string;
|
|
45
|
+
type: DependencyGroupLong;
|
|
15
46
|
};
|
|
47
|
+
export type Yarnv2OutdatedResultJson = Yarnv2VersionOverview[];
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
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;
|