Skip to content

Commit

Permalink
refactor: improve utils by splitting them & adding UT (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
fraxken authored Jul 7, 2024
1 parent 9e28f85 commit 18e5d12
Show file tree
Hide file tree
Showing 16 changed files with 260 additions and 109 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ This uses the official NodeSecure [runtime configuration](https://github.com/Nod
"i18n": "english",
"strategy": "npm",
"report": {
"title": "NodeSecure Security Report",
"logoUrl": "https://avatars.githubusercontent.com/u/85318671?s=200&v=4",
"theme": "light",
"includeTransitiveInternal": false,
"reporters": ["html", "pdf"],
Expand All @@ -83,7 +85,9 @@ This uses the official NodeSecure [runtime configuration](https://github.com/Nod
},
"git": {
"organizationUrl": "https://github.com/NodeSecure",
"repositories": []
"repositories": [
"vulnera"
]
},
"charts": [
{
Expand All @@ -110,9 +114,7 @@ This uses the official NodeSecure [runtime configuration](https://github.com/Nod
"type": "horizontalBar",
"interpolation": "d3.interpolateSinebow"
}
],
"title": "NodeSecure Security Report",
"logoUrl": "https://avatars.githubusercontent.com/u/85318671?s=200&v=4"
]
}
}
```
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
}
},
"scripts": {
"start": "node -r dotenv/config index.js",
"prepublishOnly": "pkg-ok",
"lint": "eslint index.js",
"test": "jest --coverage"
"lint": "eslint src test",
"test-only": "glob -c \"node --test-reporter=spec --test\" \"./test/**/*.spec.js\"",
"test": "c8 --all --src ./src -r html npm run test-only"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -44,7 +44,6 @@
"@nodesecure/utils": "^2.2.0",
"@openally/mutex": "^1.0.0",
"@topcli/spinner": "^2.1.2",
"dotenv": "^16.4.5",
"esbuild": "^0.22.0",
"filenamify": "^6.0.0",
"frequency-set": "^1.0.2",
Expand All @@ -56,9 +55,10 @@
},
"devDependencies": {
"@nodesecure/eslint-config": "^1.9.0",
"cross-env": "^7.0.3",
"@types/node": "^20.14.10",
"c8": "^10.1.2",
"eslint": "^9.6.0",
"jest": "^29.7.0",
"glob": "^10.4.3",
"pkg-ok": "^3.0.0"
},
"engines": {
Expand Down
43 changes: 23 additions & 20 deletions src/analysis/fetch.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
// Import Node.js Dependencies
import path from "node:path";

// Import Third-party Dependencies
import kleur from "kleur";

// Import Internal Dependencies
import { cloneGITRepository } from "../utils.js";
import { buildStatsFromNsecurePayloads } from "./extractScannerData.js";
import * as scanner from "./scanner.js";
import * as localStorage from "../localStorage.js";
import * as utils from "../utils.js";

function formatNpmPackages(organizationPrefix, packages) {
if (organizationPrefix === "") {
return packages;
}

return packages.map((pkg) => {
// in case the user has already added the organization prefix
if (pkg.startsWith(organizationPrefix)) {
return pkg;
}

return `${organizationPrefix}/${pkg}`;
});
}
import * as utils from "../utils/index.js";
import * as CONSTANTS from "../constants.js";

export async function fetchPackagesAndRepositoriesData() {
const config = localStorage.getConfig().report;
Expand All @@ -35,11 +23,21 @@ export async function fetchPackagesAndRepositoriesData() {
}

const pkgStats = fetchNpm ?
await fetchPackagesStats(formatNpmPackages(config.npm.organizationPrefix, config.npm.packages)) : null;
await fetchPackagesStats(
utils.formatNpmPackages(
config.npm.organizationPrefix,
config.npm.packages
)
) :
null;

const { repositories, organizationUrl } = config.git;
const repoStats = fetchGit ?
await fetchRepositoriesStats(repositories, organizationUrl) : null;
await fetchRepositoriesStats(
repositories,
organizationUrl
) :
null;

return { pkgStats, repoStats };
}
Expand All @@ -66,7 +64,12 @@ async function fetchRepositoriesStats(repositories, organizationUrl) {
},
async(spinner) => {
const repos = await Promise.all(
repositories.map((repositoryName) => cloneGITRepository(repositoryName, organizationUrl))
repositories.map((repositoryName) => {
return utils.cloneGITRepository(
path.join(CONSTANTS.DIRS.CLONES, repositoryName),
`${organizationUrl}/${repositoryName}.git`
);
})
);
spinner.text = "Fetching repositories metadata on the NPM Registry";

Expand Down
7 changes: 5 additions & 2 deletions src/reporting/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kleur from "kleur";
import { taggedString } from "@nodesecure/utils";

// Import Internal Dependencies
import { cleanReportName } from "../utils.js";
import * as utils from "../utils/index.js";
import * as CONSTANTS from "../constants.js";
import * as localStorage from "../localStorage.js";

Expand Down Expand Up @@ -50,7 +50,10 @@ export async function HTML(data, reportOptions = null) {
const HTMLReport = kTemplateGenerator(templatePayload)
.concat(`\n<script>\ndocument.addEventListener("DOMContentLoaded", () => {\n${charts.join("\n")}\n});\n</script>`);

const reportHTMLPath = path.join(CONSTANTS.DIRS.REPORTS, cleanReportName(config.title, ".html"));
const reportHTMLPath = path.join(
CONSTANTS.DIRS.REPORTS,
utils.cleanReportName(config.title, ".html")
);
await fs.writeFile(reportHTMLPath, HTMLReport);

spinner.text = kleur.yellow().bold("Bundling assets with esbuild");
Expand Down
2 changes: 1 addition & 1 deletion src/reporting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import kleur from "kleur";

// Import Internal Dependencies
import * as utils from "../utils.js";
import * as utils from "../utils/index.js";
import * as localStorage from "../localStorage.js";

// Import Reporters
Expand Down
12 changes: 8 additions & 4 deletions src/reporting/pdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,24 @@ import puppeteer from "puppeteer";

// Import Internal Dependencies
import * as CONSTANTS from "../constants.js";
import * as utils from "../utils.js";
import * as utils from "../utils/index.js";

export async function PDF(reportHTMLPath, options) {
export async function PDF(
reportHTMLPath,
options
) {
const { title, saveOnDisk = true } = options;

const browser = await puppeteer.launch({
args: ["--no-sandbox", "--disable-setuid-sandbox"]
});
const page = await browser.newPage();

try {
const page = await browser.newPage();
await page.emulateMediaType("print");
await page.goto(`file:${reportHTMLPath}`, {
waitUntil: "networkidle0",
timeout: 60_000
timeout: 20_000
});

const pdfBuffer = await page.pdf({
Expand All @@ -35,6 +38,7 @@ export async function PDF(reportHTMLPath, options) {
return saveOnDisk ? path : pdfBuffer;
}
finally {
await page.close();
await browser.close();
}
}
Expand Down
69 changes: 0 additions & 69 deletions src/utils.js

This file was deleted.

26 changes: 26 additions & 0 deletions src/utils/cleanReportName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Import Node.js Dependencies
import path from "node:path";

// Import Third-party Dependencies
import filenamify from "filenamify";

/**
* @function cleanReportName
* @description clean the report name
* @param {!string} name
* @param {string} [extension=null]
* @returns {string}
*/
export function cleanReportName(
name,
extension = null
) {
const cleanName = filenamify(name);
if (extension === null) {
return cleanName;
}

return path.extname(cleanName) === extension ?
cleanName :
`${cleanName}${extension}`;
}
32 changes: 32 additions & 0 deletions src/utils/cloneGITRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Import Node.js Dependencies
import fs from "node:fs";

// Import Third-party Dependencies
import git from "isomorphic-git";
import http from "isomorphic-git/http/node/index.js";

/**
* @async
* @function cloneGITRepository
* @description clone a given repository from github
* @param {!string} dir
* @param {!string} url
*
* @returns {Promise<string>}
*/
export async function cloneGITRepository(
dir,
url
) {
await git.clone({
fs,
http,
dir,
url,
token: process.env.GIT_TOKEN,
singleBranch: true,
oauth2format: "github"
});

return dir;
}
21 changes: 21 additions & 0 deletions src/utils/formatNpmPackages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @param {!string} organizationPrefix
* @param {string[]} packages
*
* @returns {string[]}
*/
export function formatNpmPackages(
organizationPrefix,
packages
) {
if (organizationPrefix === "") {
return packages;
}

return packages.map((pkg) => {
// in case the user has already added the organization prefix
return pkg.startsWith(organizationPrefix) ?
pkg :
`${organizationPrefix}/${pkg}`;
});
}
4 changes: 4 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./cleanReportName.js";
export * from "./cloneGITRepository.js";
export * from "./runInSpinner.js";
export * from "./formatNpmPackages.js";
27 changes: 27 additions & 0 deletions src/utils/runInSpinner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Import Third-party Dependencies
import { Spinner } from "@topcli/spinner";
import kleur from "kleur";

export async function runInSpinner(
options,
asyncHandler
) {
const { title, start = void 0 } = options;

const spinner = new Spinner()
.start(start, { withPrefix: `${kleur.gray().bold(title)} - ` });

try {
const response = await asyncHandler(spinner);

const elapsed = `${spinner.elapsedTime.toFixed(2)}ms`;
spinner.succeed(kleur.white().bold(`successfully executed in ${kleur.green().bold(elapsed)}`));

return response;
}
catch (err) {
spinner.failed(err.message);

throw err;
}
}
3 changes: 0 additions & 3 deletions test/test.js

This file was deleted.

Loading

0 comments on commit 18e5d12

Please sign in to comment.