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