@code-pushup/js-packages-plugin 0.30.0-alpha → 0.35.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 +15 -5
- package/bin.js +288 -131
- package/index.js +490 -94
- package/package.json +3 -3
- package/src/lib/config.d.ts +2 -2
- package/src/lib/constants.d.ts +3 -8
- package/src/lib/package-managers/constants.d.ts +2 -0
- package/src/lib/package-managers/index.d.ts +2 -0
- package/src/lib/{runner/audit/unify-type.d.ts → package-managers/npm/audit-result.d.ts} +2 -3
- package/src/lib/package-managers/npm/npm.d.ts +2 -0
- package/src/lib/package-managers/npm/outdated-result.d.ts +2 -0
- package/src/lib/package-managers/npm/types.d.ts +38 -0
- package/src/lib/package-managers/package-managers.d.ts +3 -0
- package/src/lib/package-managers/pnpm/audit-result.d.ts +3 -0
- package/src/lib/package-managers/pnpm/outdated-result.d.ts +2 -0
- package/src/lib/package-managers/pnpm/pnpm.d.ts +2 -0
- package/src/lib/package-managers/pnpm/types.d.ts +26 -0
- package/src/lib/package-managers/types.d.ts +26 -0
- package/src/lib/package-managers/yarn-classic/audit-result.d.ts +2 -0
- package/src/lib/package-managers/yarn-classic/outdated-result.d.ts +2 -0
- package/src/lib/package-managers/yarn-classic/types.d.ts +49 -0
- package/src/lib/package-managers/yarn-classic/yarn-classic.d.ts +2 -0
- package/src/lib/package-managers/yarn-modern/audit-result.d.ts +2 -0
- package/src/lib/package-managers/yarn-modern/outdated-result.d.ts +2 -0
- package/src/lib/package-managers/yarn-modern/types.d.ts +26 -0
- package/src/lib/package-managers/yarn-modern/yarn-modern.d.ts +2 -0
- package/src/lib/runner/audit/constants.d.ts +1 -4
- package/src/lib/runner/audit/transform.d.ts +2 -2
- package/src/lib/runner/audit/types.d.ts +0 -69
- package/src/lib/runner/audit/utils.d.ts +2 -0
- package/src/lib/runner/outdated/constants.d.ts +2 -5
- package/src/lib/runner/outdated/transform.d.ts +2 -2
- package/src/lib/runner/outdated/types.d.ts +0 -37
- package/src/lib/runner/outdated/unify-type.d.ts +0 -4
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.35.0";
|
|
8
8
|
|
|
9
9
|
// packages/plugin-js-packages/src/lib/config.ts
|
|
10
10
|
import { z as z15 } from "zod";
|
|
@@ -663,35 +663,16 @@ var defaultAuditLevelMapping = {
|
|
|
663
663
|
low: "warning",
|
|
664
664
|
info: "info"
|
|
665
665
|
};
|
|
666
|
-
var
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
pnpm: "PNPM"
|
|
666
|
+
var dependencyGroupToLong = {
|
|
667
|
+
prod: "dependencies",
|
|
668
|
+
dev: "devDependencies",
|
|
669
|
+
optional: "optionalDependencies"
|
|
671
670
|
};
|
|
672
|
-
var
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
};
|
|
678
|
-
var pkgManagerDocs = {
|
|
679
|
-
npm: "https://docs.npmjs.com/",
|
|
680
|
-
"yarn-classic": "https://classic.yarnpkg.com/docs/",
|
|
681
|
-
"yarn-modern": "https://yarnpkg.com/getting-started",
|
|
682
|
-
pnpm: "https://pnpm.io/pnpm-cli"
|
|
683
|
-
};
|
|
684
|
-
var auditDocs = {
|
|
685
|
-
npm: "https://docs.npmjs.com/cli/commands/npm-audit",
|
|
686
|
-
"yarn-classic": "https://classic.yarnpkg.com/docs/cli/audit",
|
|
687
|
-
"yarn-modern": "https://yarnpkg.com/cli/npm/audit",
|
|
688
|
-
pnpm: "https://pnpm.io/cli/audit/"
|
|
689
|
-
};
|
|
690
|
-
var outdatedDocs = {
|
|
691
|
-
npm: "https://docs.npmjs.com/cli/commands/npm-outdated",
|
|
692
|
-
"yarn-classic": "https://classic.yarnpkg.com/docs/cli/outdated/",
|
|
693
|
-
"yarn-modern": "https://github.com/mskelton/yarn-plugin-outdated",
|
|
694
|
-
pnpm: "https://pnpm.io/cli/outdated"
|
|
671
|
+
var dependencyGroupWeights = {
|
|
672
|
+
// eslint-disable-next-line no-magic-numbers
|
|
673
|
+
prod: 3,
|
|
674
|
+
dev: 1,
|
|
675
|
+
optional: 1
|
|
695
676
|
};
|
|
696
677
|
var dependencyDocs = {
|
|
697
678
|
prod: "https://classic.yarnpkg.com/docs/dependency-types#toc-dependencies",
|
|
@@ -700,8 +681,9 @@ var dependencyDocs = {
|
|
|
700
681
|
};
|
|
701
682
|
|
|
702
683
|
// packages/plugin-js-packages/src/lib/config.ts
|
|
684
|
+
var dependencyGroups = ["prod", "dev", "optional"];
|
|
703
685
|
var packageCommandSchema = z15.enum(["audit", "outdated"]);
|
|
704
|
-
var
|
|
686
|
+
var packageManagerIdSchema = z15.enum([
|
|
705
687
|
"npm",
|
|
706
688
|
"yarn-classic",
|
|
707
689
|
"yarn-modern",
|
|
@@ -728,15 +710,49 @@ var jsPackagesPluginConfigSchema = z15.object({
|
|
|
728
710
|
checks: z15.array(packageCommandSchema, {
|
|
729
711
|
description: "Package manager commands to be run. Defaults to both audit and outdated."
|
|
730
712
|
}).min(1).default(["audit", "outdated"]),
|
|
731
|
-
packageManager:
|
|
713
|
+
packageManager: packageManagerIdSchema.describe(
|
|
714
|
+
"Package manager to be used."
|
|
715
|
+
),
|
|
732
716
|
auditLevelMapping: z15.record(packageAuditLevelSchema, issueSeveritySchema, {
|
|
733
717
|
description: "Mapping of audit levels to issue severity. Custom mapping or overrides may be entered manually, otherwise has a default preset."
|
|
734
718
|
}).default(defaultAuditLevelMapping).transform(fillAuditLevelMapping)
|
|
735
719
|
});
|
|
736
720
|
|
|
737
|
-
// packages/plugin-js-packages/src/lib/runner/
|
|
738
|
-
|
|
739
|
-
|
|
721
|
+
// packages/plugin-js-packages/src/lib/runner/utils.ts
|
|
722
|
+
function filterAuditResult(result, key, referenceResult) {
|
|
723
|
+
if (result.vulnerabilities.length === 0) {
|
|
724
|
+
return result;
|
|
725
|
+
}
|
|
726
|
+
const uniqueResult = result.vulnerabilities.reduce(
|
|
727
|
+
(acc, ref) => {
|
|
728
|
+
const matchReference = referenceResult ?? acc;
|
|
729
|
+
const isMatch = matchReference.vulnerabilities.map((vulnerability) => vulnerability[key]).includes(ref[key]);
|
|
730
|
+
if (isMatch) {
|
|
731
|
+
return {
|
|
732
|
+
vulnerabilities: acc.vulnerabilities,
|
|
733
|
+
summary: {
|
|
734
|
+
...acc.summary,
|
|
735
|
+
[ref.severity]: acc.summary[ref.severity] - 1,
|
|
736
|
+
total: acc.summary.total - 1
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
return {
|
|
741
|
+
vulnerabilities: [...acc.vulnerabilities, ref],
|
|
742
|
+
summary: acc.summary
|
|
743
|
+
};
|
|
744
|
+
},
|
|
745
|
+
{ vulnerabilities: [], summary: result.summary }
|
|
746
|
+
);
|
|
747
|
+
return {
|
|
748
|
+
vulnerabilities: uniqueResult.vulnerabilities,
|
|
749
|
+
summary: uniqueResult.summary
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// packages/plugin-js-packages/src/lib/package-managers/constants.ts
|
|
754
|
+
var COMMON_AUDIT_ARGS = ["audit", "--json"];
|
|
755
|
+
var COMMON_OUTDATED_ARGS = ["outdated", "--json"];
|
|
740
756
|
|
|
741
757
|
// packages/utils/src/lib/file-system.ts
|
|
742
758
|
import { bundleRequire } from "bundle-require";
|
|
@@ -795,6 +811,19 @@ function pluginWorkDir(slug) {
|
|
|
795
811
|
// packages/utils/src/lib/git.ts
|
|
796
812
|
import { simpleGit } from "simple-git";
|
|
797
813
|
|
|
814
|
+
// packages/utils/src/lib/transform.ts
|
|
815
|
+
import { platform } from "node:os";
|
|
816
|
+
function objectToEntries(obj) {
|
|
817
|
+
return Object.entries(obj);
|
|
818
|
+
}
|
|
819
|
+
function toUnixNewlines(text) {
|
|
820
|
+
return platform() === "win32" ? text.replace(/\r\n/g, "\n") : text;
|
|
821
|
+
}
|
|
822
|
+
function fromJsonLines(jsonLines) {
|
|
823
|
+
const unifiedNewLines = toUnixNewlines(jsonLines).trim();
|
|
824
|
+
return JSON.parse(`[${unifiedNewLines.split("\n").join(",")}]`);
|
|
825
|
+
}
|
|
826
|
+
|
|
798
827
|
// packages/utils/src/lib/progress.ts
|
|
799
828
|
import chalk3 from "chalk";
|
|
800
829
|
import { MultiProgressBars } from "multi-progress-bars";
|
|
@@ -802,6 +831,392 @@ import { MultiProgressBars } from "multi-progress-bars";
|
|
|
802
831
|
// packages/utils/src/lib/reports/log-stdout-summary.ts
|
|
803
832
|
import chalk4 from "chalk";
|
|
804
833
|
|
|
834
|
+
// packages/plugin-js-packages/src/lib/package-managers/npm/audit-result.ts
|
|
835
|
+
function npmToAuditResult(output) {
|
|
836
|
+
const npmAudit = JSON.parse(output);
|
|
837
|
+
const vulnerabilities = objectToEntries(npmAudit.vulnerabilities).map(
|
|
838
|
+
([name2, detail]) => {
|
|
839
|
+
const advisory = npmToAdvisory(name2, npmAudit.vulnerabilities);
|
|
840
|
+
return {
|
|
841
|
+
name: name2.toString(),
|
|
842
|
+
severity: detail.severity,
|
|
843
|
+
versionRange: detail.range,
|
|
844
|
+
directDependency: detail.isDirect ? true : detail.effects[0] ?? "",
|
|
845
|
+
fixInformation: npmToFixInformation(detail.fixAvailable),
|
|
846
|
+
...advisory != null && {
|
|
847
|
+
title: advisory.title,
|
|
848
|
+
url: advisory.url
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
);
|
|
853
|
+
return {
|
|
854
|
+
vulnerabilities,
|
|
855
|
+
summary: npmAudit.metadata.vulnerabilities
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
function npmToFixInformation(fixAvailable) {
|
|
859
|
+
if (typeof fixAvailable === "boolean") {
|
|
860
|
+
return fixAvailable ? "Fix is available." : "";
|
|
861
|
+
}
|
|
862
|
+
return `Fix available: Update \`${fixAvailable.name}\` to version **${fixAvailable.version}**${fixAvailable.isSemVerMajor ? " (breaking change)." : "."}`;
|
|
863
|
+
}
|
|
864
|
+
function npmToAdvisory(name2, vulnerabilities, prevNodes = /* @__PURE__ */ new Set()) {
|
|
865
|
+
const advisory = vulnerabilities[name2]?.via;
|
|
866
|
+
if (Array.isArray(advisory) && advisory.length > 0 && typeof advisory[0] === "object") {
|
|
867
|
+
return { title: advisory[0].title, url: advisory[0].url };
|
|
868
|
+
}
|
|
869
|
+
if (Array.isArray(advisory) && advisory.length > 0 && advisory.every((value) => typeof value === "string")) {
|
|
870
|
+
let advisoryInfo = null;
|
|
871
|
+
let newReferences = [];
|
|
872
|
+
let advisoryInfoFound = false;
|
|
873
|
+
for (const via of advisory) {
|
|
874
|
+
if (!prevNodes.has(via)) {
|
|
875
|
+
newReferences.push(via);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
while (newReferences.length > 0 && !advisoryInfoFound) {
|
|
879
|
+
const ref = newReferences.pop();
|
|
880
|
+
prevNodes.add(ref);
|
|
881
|
+
const result = npmToAdvisory(ref, vulnerabilities, prevNodes);
|
|
882
|
+
if (result != null) {
|
|
883
|
+
advisoryInfo = { title: result.title, url: result.url };
|
|
884
|
+
advisoryInfoFound = true;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return advisoryInfo;
|
|
888
|
+
}
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// packages/plugin-js-packages/src/lib/package-managers/npm/outdated-result.ts
|
|
893
|
+
function npmToOutdatedResult(output) {
|
|
894
|
+
const npmOutdated = JSON.parse(output);
|
|
895
|
+
return objectToEntries(npmOutdated).filter(
|
|
896
|
+
(entry) => entry[1].current != null
|
|
897
|
+
).map(([name2, overview]) => ({
|
|
898
|
+
name: name2,
|
|
899
|
+
current: overview.current,
|
|
900
|
+
latest: overview.latest,
|
|
901
|
+
type: overview.type,
|
|
902
|
+
...overview.homepage != null && { url: overview.homepage }
|
|
903
|
+
}));
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// packages/plugin-js-packages/src/lib/package-managers/npm/npm.ts
|
|
907
|
+
var npmDependencyOptions = {
|
|
908
|
+
prod: ["--omit=dev", "--omit=optional"],
|
|
909
|
+
dev: ["--include=dev", "--omit=optional"],
|
|
910
|
+
optional: ["--include=optional", "--omit=dev"]
|
|
911
|
+
};
|
|
912
|
+
var npmPackageManager = {
|
|
913
|
+
slug: "npm",
|
|
914
|
+
name: "NPM",
|
|
915
|
+
command: "npm",
|
|
916
|
+
icon: "npm",
|
|
917
|
+
docs: {
|
|
918
|
+
homepage: "https://docs.npmjs.com/",
|
|
919
|
+
audit: "https://docs.npmjs.com/cli/commands/npm-audit",
|
|
920
|
+
outdated: "https://docs.npmjs.com/cli/commands/npm-outdated"
|
|
921
|
+
},
|
|
922
|
+
audit: {
|
|
923
|
+
getCommandArgs: (groupDep) => [
|
|
924
|
+
...COMMON_AUDIT_ARGS,
|
|
925
|
+
...npmDependencyOptions[groupDep],
|
|
926
|
+
"--audit-level=none"
|
|
927
|
+
],
|
|
928
|
+
unifyResult: npmToAuditResult,
|
|
929
|
+
// prod dependencies need to be filtered out manually since v10
|
|
930
|
+
postProcessResult: (results) => ({
|
|
931
|
+
prod: results.prod,
|
|
932
|
+
dev: filterAuditResult(results.dev, "name", results.prod),
|
|
933
|
+
optional: filterAuditResult(results.optional, "name", results.prod)
|
|
934
|
+
})
|
|
935
|
+
},
|
|
936
|
+
outdated: {
|
|
937
|
+
commandArgs: [...COMMON_OUTDATED_ARGS, "--long"],
|
|
938
|
+
unifyResult: npmToOutdatedResult
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
|
|
942
|
+
// packages/plugin-js-packages/src/lib/runner/audit/utils.ts
|
|
943
|
+
function getVulnerabilitiesTotal(summary) {
|
|
944
|
+
return Object.values(summary).reduce((acc, value) => acc + value, 0);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// packages/plugin-js-packages/src/lib/package-managers/pnpm/audit-result.ts
|
|
948
|
+
function pnpmToAuditResult(output) {
|
|
949
|
+
const pnpmResult = JSON.parse(output);
|
|
950
|
+
const vulnerabilities = Object.values(pnpmResult.advisories).map(
|
|
951
|
+
({
|
|
952
|
+
module_name: name2,
|
|
953
|
+
id,
|
|
954
|
+
title,
|
|
955
|
+
url,
|
|
956
|
+
severity,
|
|
957
|
+
vulnerable_versions: versionRange,
|
|
958
|
+
recommendation: fixInformation,
|
|
959
|
+
findings
|
|
960
|
+
}) => {
|
|
961
|
+
const path = findings[0]?.paths[0];
|
|
962
|
+
return {
|
|
963
|
+
name: name2,
|
|
964
|
+
id,
|
|
965
|
+
title,
|
|
966
|
+
url,
|
|
967
|
+
severity,
|
|
968
|
+
versionRange,
|
|
969
|
+
directDependency: path == null ? true : pnpmToDirectDependency(path),
|
|
970
|
+
fixInformation
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
);
|
|
974
|
+
return {
|
|
975
|
+
vulnerabilities,
|
|
976
|
+
summary: {
|
|
977
|
+
...pnpmResult.metadata.vulnerabilities,
|
|
978
|
+
total: getVulnerabilitiesTotal(pnpmResult.metadata.vulnerabilities)
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
function pnpmToDirectDependency(path) {
|
|
983
|
+
const deps = path.split(" > ").slice(1);
|
|
984
|
+
if (deps.length <= 1) {
|
|
985
|
+
return true;
|
|
986
|
+
}
|
|
987
|
+
return deps[0]?.split("@")[0] ?? true;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// packages/plugin-js-packages/src/lib/package-managers/pnpm/outdated-result.ts
|
|
991
|
+
function pnpmToOutdatedResult(output) {
|
|
992
|
+
const pnpmOutdated = JSON.parse(output);
|
|
993
|
+
return objectToEntries(pnpmOutdated).map(
|
|
994
|
+
([name2, { current, latest, dependencyType: type }]) => ({
|
|
995
|
+
name: name2,
|
|
996
|
+
current,
|
|
997
|
+
latest,
|
|
998
|
+
type
|
|
999
|
+
})
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// packages/plugin-js-packages/src/lib/package-managers/pnpm/pnpm.ts
|
|
1004
|
+
var pnpmDependencyOptions = {
|
|
1005
|
+
prod: ["--prod", "--no-optional"],
|
|
1006
|
+
dev: ["--dev", "--no-optional"],
|
|
1007
|
+
optional: []
|
|
1008
|
+
};
|
|
1009
|
+
var pnpmPackageManager = {
|
|
1010
|
+
slug: "pnpm",
|
|
1011
|
+
name: "pnpm",
|
|
1012
|
+
command: "pnpm",
|
|
1013
|
+
icon: "pnpm",
|
|
1014
|
+
docs: {
|
|
1015
|
+
homepage: "https://pnpm.io/pnpm-cli",
|
|
1016
|
+
audit: "https://pnpm.io/cli/audit/",
|
|
1017
|
+
outdated: "https://pnpm.io/cli/outdated"
|
|
1018
|
+
},
|
|
1019
|
+
audit: {
|
|
1020
|
+
getCommandArgs: (groupDep) => [
|
|
1021
|
+
...COMMON_AUDIT_ARGS,
|
|
1022
|
+
...pnpmDependencyOptions[groupDep]
|
|
1023
|
+
],
|
|
1024
|
+
ignoreExitCode: true,
|
|
1025
|
+
unifyResult: pnpmToAuditResult,
|
|
1026
|
+
// optional dependencies don't have an exclusive option so they need duplicates filtered out
|
|
1027
|
+
postProcessResult: (results) => ({
|
|
1028
|
+
prod: results.prod,
|
|
1029
|
+
dev: results.dev,
|
|
1030
|
+
optional: filterAuditResult(
|
|
1031
|
+
filterAuditResult(results.optional, "id", results.prod),
|
|
1032
|
+
"id",
|
|
1033
|
+
results.dev
|
|
1034
|
+
)
|
|
1035
|
+
})
|
|
1036
|
+
},
|
|
1037
|
+
outdated: {
|
|
1038
|
+
commandArgs: COMMON_OUTDATED_ARGS,
|
|
1039
|
+
unifyResult: pnpmToOutdatedResult
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
|
|
1043
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-classic/audit-result.ts
|
|
1044
|
+
function yarnv1ToAuditResult(output) {
|
|
1045
|
+
const yarnv1Result = fromJsonLines(output);
|
|
1046
|
+
const [yarnv1Advisory, yarnv1Summary] = validateYarnv1Result(yarnv1Result);
|
|
1047
|
+
const vulnerabilities = yarnv1Advisory.map(
|
|
1048
|
+
({ data: { resolution, advisory } }) => {
|
|
1049
|
+
const { id, path } = resolution;
|
|
1050
|
+
const directDependency = path.slice(0, path.indexOf(">"));
|
|
1051
|
+
const {
|
|
1052
|
+
module_name: name2,
|
|
1053
|
+
title,
|
|
1054
|
+
url,
|
|
1055
|
+
severity,
|
|
1056
|
+
vulnerable_versions: versionRange,
|
|
1057
|
+
recommendation: fixInformation
|
|
1058
|
+
} = advisory;
|
|
1059
|
+
return {
|
|
1060
|
+
name: name2,
|
|
1061
|
+
title,
|
|
1062
|
+
id,
|
|
1063
|
+
url,
|
|
1064
|
+
severity,
|
|
1065
|
+
versionRange,
|
|
1066
|
+
directDependency: name2 === directDependency ? true : directDependency,
|
|
1067
|
+
fixInformation
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
const summary = {
|
|
1072
|
+
...yarnv1Summary.data.vulnerabilities,
|
|
1073
|
+
total: Object.values(yarnv1Summary.data.vulnerabilities).reduce(
|
|
1074
|
+
(acc, amount) => acc + amount,
|
|
1075
|
+
0
|
|
1076
|
+
)
|
|
1077
|
+
};
|
|
1078
|
+
return filterAuditResult({ vulnerabilities, summary }, "id");
|
|
1079
|
+
}
|
|
1080
|
+
function validateYarnv1Result(result) {
|
|
1081
|
+
const summary = result.at(-1);
|
|
1082
|
+
if (summary?.type !== "auditSummary") {
|
|
1083
|
+
throw new Error("Invalid Yarn v1 audit result - no summary found.");
|
|
1084
|
+
}
|
|
1085
|
+
const vulnerabilities = result.filter(
|
|
1086
|
+
(item) => item.type === "auditAdvisory"
|
|
1087
|
+
);
|
|
1088
|
+
return [vulnerabilities, summary];
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-classic/outdated-result.ts
|
|
1092
|
+
function yarnv1ToOutdatedResult(output) {
|
|
1093
|
+
const yarnv1Outdated = fromJsonLines(output);
|
|
1094
|
+
const dependencies = yarnv1Outdated[1].data.body;
|
|
1095
|
+
return dependencies.map(([name2, current, _, latest, __, type, url]) => ({
|
|
1096
|
+
name: name2,
|
|
1097
|
+
current,
|
|
1098
|
+
latest,
|
|
1099
|
+
type,
|
|
1100
|
+
url
|
|
1101
|
+
}));
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-classic/yarn-classic.ts
|
|
1105
|
+
var yarnv1PackageManager = {
|
|
1106
|
+
slug: "yarn-classic",
|
|
1107
|
+
name: "Yarn v1",
|
|
1108
|
+
command: "yarn",
|
|
1109
|
+
icon: "yarn",
|
|
1110
|
+
docs: {
|
|
1111
|
+
homepage: "https://classic.yarnpkg.com/docs/",
|
|
1112
|
+
audit: "https://classic.yarnpkg.com/docs/cli/audit",
|
|
1113
|
+
outdated: "https://classic.yarnpkg.com/docs/cli/outdated/"
|
|
1114
|
+
},
|
|
1115
|
+
audit: {
|
|
1116
|
+
getCommandArgs: (groupDep) => [
|
|
1117
|
+
...COMMON_AUDIT_ARGS,
|
|
1118
|
+
"--groups",
|
|
1119
|
+
dependencyGroupToLong[groupDep]
|
|
1120
|
+
],
|
|
1121
|
+
ignoreExitCode: true,
|
|
1122
|
+
unifyResult: yarnv1ToAuditResult
|
|
1123
|
+
},
|
|
1124
|
+
outdated: {
|
|
1125
|
+
commandArgs: COMMON_OUTDATED_ARGS,
|
|
1126
|
+
unifyResult: yarnv1ToOutdatedResult
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-modern/audit-result.ts
|
|
1131
|
+
function yarnv2ToAuditResult(output) {
|
|
1132
|
+
const yarnv2Audit = JSON.parse(output);
|
|
1133
|
+
const vulnerabilities = Object.values(yarnv2Audit.advisories).map(
|
|
1134
|
+
({
|
|
1135
|
+
module_name: name2,
|
|
1136
|
+
severity,
|
|
1137
|
+
title,
|
|
1138
|
+
url,
|
|
1139
|
+
vulnerable_versions: versionRange,
|
|
1140
|
+
recommendation: fixInformation,
|
|
1141
|
+
findings
|
|
1142
|
+
}) => {
|
|
1143
|
+
const directDep = findings[0]?.paths[0];
|
|
1144
|
+
return {
|
|
1145
|
+
name: name2,
|
|
1146
|
+
severity,
|
|
1147
|
+
title,
|
|
1148
|
+
url,
|
|
1149
|
+
versionRange,
|
|
1150
|
+
fixInformation,
|
|
1151
|
+
directDependency: directDep != null && directDep !== name2 ? directDep : true
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
);
|
|
1155
|
+
return {
|
|
1156
|
+
vulnerabilities,
|
|
1157
|
+
summary: {
|
|
1158
|
+
...yarnv2Audit.metadata.vulnerabilities,
|
|
1159
|
+
total: getVulnerabilitiesTotal(yarnv2Audit.metadata.vulnerabilities)
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-modern/outdated-result.ts
|
|
1165
|
+
function yarnv2ToOutdatedResult(output) {
|
|
1166
|
+
const npmOutdated = JSON.parse(output);
|
|
1167
|
+
return npmOutdated.map(({ name: name2, current, latest, type }) => ({
|
|
1168
|
+
name: name2,
|
|
1169
|
+
current,
|
|
1170
|
+
latest,
|
|
1171
|
+
type
|
|
1172
|
+
}));
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// packages/plugin-js-packages/src/lib/package-managers/yarn-modern/yarn-modern.ts
|
|
1176
|
+
var yarnv2EnvironmentOptions = {
|
|
1177
|
+
prod: "production",
|
|
1178
|
+
dev: "development",
|
|
1179
|
+
optional: ""
|
|
1180
|
+
};
|
|
1181
|
+
var yarnv2PackageManager = {
|
|
1182
|
+
slug: "yarn-modern",
|
|
1183
|
+
name: "yarn-modern",
|
|
1184
|
+
command: "yarn",
|
|
1185
|
+
icon: "yarn",
|
|
1186
|
+
docs: {
|
|
1187
|
+
homepage: "https://yarnpkg.com/getting-started",
|
|
1188
|
+
audit: "https://yarnpkg.com/cli/npm/audit",
|
|
1189
|
+
outdated: "https://github.com/mskelton/yarn-plugin-outdated"
|
|
1190
|
+
},
|
|
1191
|
+
audit: {
|
|
1192
|
+
getCommandArgs: (groupDep) => [
|
|
1193
|
+
"npm",
|
|
1194
|
+
...COMMON_AUDIT_ARGS,
|
|
1195
|
+
"--environment",
|
|
1196
|
+
yarnv2EnvironmentOptions[groupDep]
|
|
1197
|
+
],
|
|
1198
|
+
supportedDepGroups: ["prod", "dev"],
|
|
1199
|
+
// Yarn v2 does not support audit for optional dependencies
|
|
1200
|
+
unifyResult: yarnv2ToAuditResult
|
|
1201
|
+
},
|
|
1202
|
+
outdated: {
|
|
1203
|
+
commandArgs: COMMON_OUTDATED_ARGS,
|
|
1204
|
+
unifyResult: yarnv2ToOutdatedResult
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
// packages/plugin-js-packages/src/lib/package-managers/package-managers.ts
|
|
1209
|
+
var packageManagers = {
|
|
1210
|
+
npm: npmPackageManager,
|
|
1211
|
+
"yarn-classic": yarnv1PackageManager,
|
|
1212
|
+
"yarn-modern": yarnv2PackageManager,
|
|
1213
|
+
pnpm: pnpmPackageManager
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
// packages/plugin-js-packages/src/lib/runner/index.ts
|
|
1217
|
+
import { writeFile } from "node:fs/promises";
|
|
1218
|
+
import { dirname } from "node:path";
|
|
1219
|
+
|
|
805
1220
|
// packages/plugin-js-packages/src/lib/runner/constants.ts
|
|
806
1221
|
import { join as join2 } from "node:path";
|
|
807
1222
|
var WORKDIR = pluginWorkDir("js-packages");
|
|
@@ -826,8 +1241,9 @@ async function createRunnerConfig(scriptPath, config) {
|
|
|
826
1241
|
// packages/plugin-js-packages/src/lib/js-packages-plugin.ts
|
|
827
1242
|
async function jsPackagesPlugin(config) {
|
|
828
1243
|
const jsPackagesPluginConfig = jsPackagesPluginConfigSchema.parse(config);
|
|
829
|
-
const pkgManager = jsPackagesPluginConfig.packageManager;
|
|
830
1244
|
const checks = [...new Set(jsPackagesPluginConfig.checks)];
|
|
1245
|
+
const id = jsPackagesPluginConfig.packageManager;
|
|
1246
|
+
const pm = packageManagers[id];
|
|
831
1247
|
const runnerScriptPath = join3(
|
|
832
1248
|
fileURLToPath(dirname2(import.meta.url)),
|
|
833
1249
|
"bin.js"
|
|
@@ -835,81 +1251,61 @@ async function jsPackagesPlugin(config) {
|
|
|
835
1251
|
return {
|
|
836
1252
|
slug: "js-packages",
|
|
837
1253
|
title: "JS Packages",
|
|
838
|
-
icon:
|
|
1254
|
+
icon: pm.icon,
|
|
839
1255
|
description: "This plugin runs audit to uncover vulnerabilities and lists outdated dependencies. It supports npm, yarn classic, yarn modern, and pnpm package managers.",
|
|
840
|
-
docsUrl:
|
|
1256
|
+
docsUrl: pm.docs.homepage,
|
|
841
1257
|
packageName: name,
|
|
842
1258
|
version,
|
|
843
|
-
audits: createAudits(
|
|
844
|
-
groups: createGroups(
|
|
1259
|
+
audits: createAudits(id, checks),
|
|
1260
|
+
groups: createGroups(id, checks),
|
|
845
1261
|
runner: await createRunnerConfig(runnerScriptPath, jsPackagesPluginConfig)
|
|
846
1262
|
};
|
|
847
1263
|
}
|
|
848
|
-
function createGroups(
|
|
1264
|
+
function createGroups(id, checks) {
|
|
1265
|
+
const pm = packageManagers[id];
|
|
1266
|
+
const supportedAuditDepGroups = pm.audit.supportedDepGroups ?? dependencyGroups;
|
|
849
1267
|
const groups = {
|
|
850
1268
|
audit: {
|
|
851
|
-
slug: `${
|
|
852
|
-
title: `${
|
|
853
|
-
description: `Group containing ${
|
|
854
|
-
docsUrl:
|
|
855
|
-
refs:
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
-
]
|
|
866
|
-
]
|
|
1269
|
+
slug: `${pm.slug}-audit`,
|
|
1270
|
+
title: `${pm.name} audit`,
|
|
1271
|
+
description: `Group containing ${pm.name} vulnerabilities.`,
|
|
1272
|
+
docsUrl: pm.docs.audit,
|
|
1273
|
+
refs: supportedAuditDepGroups.map((depGroup) => ({
|
|
1274
|
+
slug: `${pm.slug}-audit-${depGroup}`,
|
|
1275
|
+
weight: dependencyGroupWeights[depGroup]
|
|
1276
|
+
}))
|
|
867
1277
|
},
|
|
868
1278
|
outdated: {
|
|
869
|
-
slug: `${
|
|
870
|
-
title: `${
|
|
871
|
-
description: `Group containing outdated ${
|
|
872
|
-
docsUrl:
|
|
873
|
-
refs:
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
{ slug: `${pkgManager}-outdated-optional`, weight: 1 }
|
|
878
|
-
]
|
|
1279
|
+
slug: `${pm.slug}-outdated`,
|
|
1280
|
+
title: `${pm.name} outdated dependencies`,
|
|
1281
|
+
description: `Group containing outdated ${pm.name} dependencies.`,
|
|
1282
|
+
docsUrl: pm.docs.outdated,
|
|
1283
|
+
refs: dependencyGroups.map((depGroup) => ({
|
|
1284
|
+
slug: `${pm.slug}-outdated-${depGroup}`,
|
|
1285
|
+
weight: dependencyGroupWeights[depGroup]
|
|
1286
|
+
}))
|
|
879
1287
|
}
|
|
880
1288
|
};
|
|
881
1289
|
return checks.map((check) => groups[check]);
|
|
882
1290
|
}
|
|
883
|
-
function createAudits(
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
description: getAuditDescription(check, "dev"),
|
|
895
|
-
docsUrl: dependencyDocs.dev
|
|
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
|
-
]
|
|
906
|
-
]);
|
|
1291
|
+
function createAudits(id, checks) {
|
|
1292
|
+
const { slug } = packageManagers[id];
|
|
1293
|
+
return checks.flatMap((check) => {
|
|
1294
|
+
const supportedDepGroups = check === "audit" ? packageManagers[id].audit.supportedDepGroups ?? dependencyGroups : dependencyGroups;
|
|
1295
|
+
return supportedDepGroups.map((depGroup) => ({
|
|
1296
|
+
slug: `${slug}-${check}-${depGroup}`,
|
|
1297
|
+
title: getAuditTitle(slug, check, depGroup),
|
|
1298
|
+
description: getAuditDescription(check, depGroup),
|
|
1299
|
+
docsUrl: dependencyDocs[depGroup]
|
|
1300
|
+
}));
|
|
1301
|
+
});
|
|
907
1302
|
}
|
|
908
|
-
function getAuditTitle(
|
|
909
|
-
|
|
1303
|
+
function getAuditTitle(id, check, depGroup) {
|
|
1304
|
+
const pm = packageManagers[id];
|
|
1305
|
+
return check === "audit" ? `Vulnerabilities for ${pm.name} ${depGroup} dependencies.` : `Outdated ${pm.name} ${depGroup} dependencies.`;
|
|
910
1306
|
}
|
|
911
|
-
function getAuditDescription(check,
|
|
912
|
-
return check === "audit" ? `Runs security audit on ${
|
|
1307
|
+
function getAuditDescription(check, depGroup) {
|
|
1308
|
+
return check === "audit" ? `Runs security audit on ${depGroup} dependencies.` : `Checks for outdated ${depGroup} dependencies`;
|
|
913
1309
|
}
|
|
914
1310
|
|
|
915
1311
|
// packages/plugin-js-packages/src/index.ts
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-pushup/js-packages-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"@code-pushup/models": "
|
|
6
|
-
"@code-pushup/utils": "
|
|
5
|
+
"@code-pushup/models": "0.35.0",
|
|
6
|
+
"@code-pushup/utils": "0.35.0",
|
|
7
7
|
"zod": "^3.22.4"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
package/src/lib/config.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export declare const dependencyGroups: readonly ["prod", "dev", "optional"];
|
|
|
4
4
|
export type DependencyGroup = (typeof dependencyGroups)[number];
|
|
5
5
|
declare const packageCommandSchema: z.ZodEnum<["audit", "outdated"]>;
|
|
6
6
|
export type PackageCommand = z.infer<typeof packageCommandSchema>;
|
|
7
|
-
declare const
|
|
8
|
-
export type
|
|
7
|
+
declare const packageManagerIdSchema: z.ZodEnum<["npm", "yarn-classic", "yarn-modern", "pnpm"]>;
|
|
8
|
+
export type PackageManagerId = z.infer<typeof packageManagerIdSchema>;
|
|
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>;
|