Skip to content

Commit 7d357e0

Browse files
feat(cli): generate report (#403)
1 parent 6b58f4d commit 7d357e0

File tree

7 files changed

+109
-5
lines changed

7 files changed

+109
-5
lines changed

bin/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ prog
9494
.option("--vcs", i18n.getTokenSync("cli.commands.scorecard.option_vcs"), "github")
9595
.action(commands.scorecard.main);
9696

97+
prog
98+
.command("report [repository]")
99+
.describe(i18n.getTokenSync("cli.commands.report.desc"))
100+
.option("-t, --theme", i18n.getTokenSync("cli.commands.report.option_theme"), "white")
101+
.option("-i, --includesAllDeps", i18n.getTokenSync("cli.commands.report.option_includesAllDeps"), true)
102+
.option("-l, --title", i18n.getTokenSync("cli.commands.report.option_title"), "NodeSecure Report")
103+
.option("-r, --reporters", i18n.getTokenSync("cli.commands.report.option_reporters"), ["html"])
104+
.action(commands.report.main);
105+
97106
prog
98107
.command("lang")
99108
.describe(i18n.getTokenSync("cli.commands.lang.desc"))

i18n/english.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ const cli = {
5454
desc: "Display the OSSF Scorecard for a given repository or the current working directory (Github only, e.g. fastify/fastify)",
5555
option_vcs: "Version control platform (GitHub, GitLab)"
5656
},
57+
report: {
58+
desc: "Generate a report from a package",
59+
option_includesAllDeps: "Include all dependencies",
60+
option_theme: "Report theme ('dark', 'light')",
61+
option_title: "Report title",
62+
option_reporters: "List of reporters to use: 'html', 'pdf'"
63+
},
5764
config: {
5865
desc: "Edit your NodeSecure config file"
5966
},

i18n/french.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ const cli = {
5454
desc: "Afficher la fiche de score OSSF du repo donné ou du repertoire actuel (Github uniquement ex. fastify/fastify)",
5555
option_vcs: "Logiciel de gestion de versions (GitHub, GitLab)"
5656
},
57+
report: {
58+
desc: "Générer un rapport à partir d'un package",
59+
option_includesAllDeps: "Inclure toutes les dépendances, true par défaut",
60+
option_theme: "Thème du rapport ('dark', 'light'), 'light' par défaut",
61+
option_title: "Titre du rapport",
62+
option_reporters: "Liste des reporters à utiliser 'html', 'pdf'"
63+
},
5764
config: {
5865
desc: "Modifier le fichier de configuration NodeSecure"
5966
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"@nodesecure/npm-registry-sdk": "^3.0.0",
8787
"@nodesecure/ossf-scorecard-sdk": "^3.2.1",
8888
"@nodesecure/rc": "^2.1.0",
89-
"@nodesecure/report": "^1.2.1",
89+
"@nodesecure/report": "^2.1.0",
9090
"@nodesecure/scanner": "^5.3.0",
9191
"@nodesecure/utils": "^2.2.0",
9292
"@nodesecure/vuln": "^1.7.0",

src/commands/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * as http from "./http.js";
66
export * as scanner from "./scanner.js";
77
export * as config from "./config.js";
88
export * as scorecard from "./scorecard.js";
9+
export * as report from "./report.js";

src/commands/report.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Import Third-party Dependencikes
2+
import { report } from "@nodesecure/report";
3+
import * as scanner from "@nodesecure/scanner";
4+
5+
// CONSTANTS
6+
const kSupportedReporters = new Set(["html", "pdf"]);
7+
const kReportPayload = {
8+
includeTransitiveInternal: false,
9+
charts: [
10+
{
11+
name: "Extensions",
12+
display: true,
13+
interpolation: "d3.interpolateRainbow",
14+
type: "bar"
15+
},
16+
{
17+
name: "Licenses",
18+
display: true,
19+
interpolation: "d3.interpolateCool",
20+
type: "bar"
21+
},
22+
{
23+
name: "Warnings",
24+
display: true,
25+
type: "horizontalBar",
26+
interpolation: "d3.interpolateInferno"
27+
},
28+
{
29+
name: "Flags",
30+
display: true,
31+
type: "horizontalBar",
32+
interpolation: "d3.interpolateSinebow"
33+
}
34+
]
35+
};
36+
export async function main(repository, options) {
37+
const {
38+
theme,
39+
includesAllDeps,
40+
title,
41+
reporters
42+
} = options;
43+
44+
const [organizationPrefixOrRepo, repo] = repository.split("/");
45+
46+
const formattedReporters = new Set(Array.isArray(reporters) ? reporters : [reporters]);
47+
for (const reporter of formattedReporters) {
48+
if (!kSupportedReporters.has(reporter)) {
49+
console.error(`Reporter '${reporter}' is not supported`);
50+
process.exit();
51+
}
52+
}
53+
54+
const reportPayload = {
55+
...kReportPayload,
56+
npm: {
57+
organizationPrefix: repo === undefined ? null : organizationPrefixOrRepo,
58+
packages: [repo === undefined ? organizationPrefixOrRepo : repo]
59+
},
60+
theme,
61+
title,
62+
reporters: [...formattedReporters],
63+
saveOnDisk: true
64+
};
65+
const scannerPayload = await scanner.from(repository);
66+
67+
const reportPath = await report(
68+
includesAllDeps ? scannerPayload.dependencies : { [repository]: scannerPayload.dependencies[repository] },
69+
reportPayload,
70+
{
71+
reportOutputLocation: process.cwd(),
72+
savePDFOnDisk: formattedReporters.has("pdf"),
73+
saveHTMLOnDisk: formattedReporters.has("html")
74+
}
75+
);
76+
77+
console.log("Successfully generated report", reportPath);
78+
}

src/http-server/endpoints/report.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export async function post(req, res) {
4848
const { title, includesAllDeps, theme } = body;
4949
const { dataFilePath } = context.getStore();
5050
const scannerPayload = JSON.parse(fs.readFileSync(dataFilePath, "utf-8"));
51-
const reportPayload = kReportPayload;
51+
const reportPayload = structuredClone(kReportPayload);
5252
const rootDependencyName = scannerPayload.rootDependencyName;
5353
const [organizationPrefixOrRepo, repo] = rootDependencyName.split("/");
5454
Object.assign(reportPayload, {
@@ -62,8 +62,8 @@ export async function post(req, res) {
6262

6363
try {
6464
const data = await report(
65-
reportPayload,
66-
includesAllDeps ? scannerPayload.dependencies : { [rootDependencyName]: scannerPayload.dependencies[rootDependencyName] }
65+
includesAllDeps ? scannerPayload.dependencies : { [rootDependencyName]: scannerPayload.dependencies[rootDependencyName] },
66+
reportPayload
6767
);
6868

6969
return send(res, 200, {
@@ -72,7 +72,9 @@ export async function post(req, res) {
7272
"Content-type": "application/pdf"
7373
});
7474
}
75-
catch {
75+
catch (err) {
76+
console.error(err);
77+
7678
return send(
7779
res,
7880
500

0 commit comments

Comments
 (0)