-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: update to esm * refacto: update dependencies * refacto: fix lint * refactor: dependencies update + lint * refacto: fix bug
- Loading branch information
Showing
14 changed files
with
17,869 additions
and
12,158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,14 @@ | ||
# Editor configuration, see https://editorconfig.org | ||
root = true | ||
|
||
[*] | ||
indent_size = 4 | ||
indent_style = space | ||
end_of_line = lf | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
indent_style = space | ||
indent_size = 2 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
end_of_line = lf | ||
|
||
[*.md] | ||
max_line_length = off | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
{ | ||
"extends": "@slimio/eslint-config", | ||
"rules": { | ||
"jsdoc/require-jsdoc": "off" | ||
"extends": "@nodesecure/eslint-config", | ||
"parserOptions": { | ||
"sourceType": "module", | ||
"requireConfigFile": false | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,152 +1,156 @@ | ||
/* eslint-disable max-depth */ | ||
"use strict"; | ||
|
||
require("dotenv").config(); | ||
require("make-promises-safe"); | ||
|
||
/* eslint-disable max-depth, max-len */ | ||
// Require Node.js Dependencies | ||
const { join, basename } = require("path"); | ||
const { readdirSync, promises: { mkdir, rmdir, readFile, writeFile } } = require("fs"); | ||
import path from "path"; | ||
import fs, { promises } from "fs"; | ||
import { fileURLToPath } from "url"; | ||
|
||
// Require Third-party Dependencies | ||
const { cyan, white } = require("kleur"); | ||
const { taggedString } = require("@slimio/utils"); | ||
const compile = require("zup"); | ||
const Spinner = require("@slimio/async-cli-spinner"); | ||
import dotenv from "dotenv"; | ||
dotenv.config(); | ||
|
||
import kleur from "kleur"; | ||
import { taggedString } from "@slimio/utils"; | ||
import compile from "zup"; | ||
import Spinner from "@slimio/async-cli-spinner"; | ||
Spinner.DEFAULT_SPINNER = "dots"; | ||
|
||
// Require Internal Dependencies | ||
const { cloneGITRepository, fetchStatsFromNsecurePayloads, nsecure, cleanReportName } = require("./src/utils"); | ||
const { generatePDF } = require("./src/pdf"); | ||
const config = require("./data/config.json"); | ||
import { cloneGITRepository, fetchStatsFromNsecurePayloads, nsecure, cleanReportName } from "./src/utils.js"; | ||
import { generatePDF } from "./src/pdf.js"; | ||
const config = JSON.parse( | ||
fs.readFileSync(new URL("./data/config.json", import.meta.url)) | ||
); | ||
|
||
// CONSTANTS | ||
const kCloneDir = join(__dirname, "clones"); | ||
const kJsonDir = join(__dirname, "json"); | ||
const kViewsDir = join(__dirname, "views"); | ||
const kReportsDir = join(__dirname, "reports"); | ||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
const kCloneDir = path.join(__dirname, "clones"); | ||
const kJsonDir = path.join(__dirname, "json"); | ||
const kViewsDir = path.join(__dirname, "views"); | ||
const kReportsDir = path.join(__dirname, "reports"); | ||
const kChartTemplate = taggedString`\tcreateChart("${0}", "${4}", { labels: [${1}], interpolate: ${3}, data: [${2}] });`; | ||
const kAvailableThemes = new Set(readdirSync(join(__dirname, "public", "css", "themes")).map((file) => basename(file, ".css"))); | ||
const kAvailableThemes = new Set(fs.readdirSync(path.join(__dirname, "public", "css", "themes")).map((file) => path.basename(file, ".css"))); | ||
|
||
async function fetchPackagesStats() { | ||
const spinner = new Spinner({ | ||
prefixText: white().bold("Fetching packages stats on nsecure") | ||
}).start(); | ||
|
||
try { | ||
const jsonFiles = await Promise.all(config.npm_packages.map(nsecure.onPackage)); | ||
const elapsed = `${spinner.elapsedTime.toFixed(2)}ms`; | ||
spinner.succeed(`Successfully done in ${cyan().bold(elapsed)}`); | ||
|
||
return fetchStatsFromNsecurePayloads(jsonFiles.filter((value) => value !== null)); | ||
} | ||
catch (error) { | ||
spinner.failed(error.message); | ||
throw error; | ||
} | ||
const spinner = new Spinner({ | ||
prefixText: kleur.white().bold("Fetching packages stats on nsecure") | ||
}).start(); | ||
|
||
try { | ||
const jsonFiles = await Promise.all(config.npm_packages.map(nsecure.onPackage)); | ||
const elapsed = `${spinner.elapsedTime.toFixed(2)}ms`; | ||
spinner.succeed(`Successfully done in ${kleur.cyan().bold(elapsed)}`); | ||
|
||
return fetchStatsFromNsecurePayloads(jsonFiles.filter((value) => value !== null)); | ||
} | ||
catch (error) { | ||
spinner.failed(error.message); | ||
throw error; | ||
} | ||
} | ||
|
||
async function fetchRepositoriesStats() { | ||
const spinner = new Spinner({ | ||
prefixText: white().bold("Clone and analyze built-in addons") | ||
}).start("clone repositories..."); | ||
|
||
try { | ||
const repos = await Promise.all(config.git_repositories.map(cloneGITRepository)); | ||
spinner.text = "Run node-secure analyze"; | ||
|
||
const jsonFiles = await Promise.all(repos.map(nsecure.onLocalDirectory)); | ||
const elapsed = `${spinner.elapsedTime.toFixed(2)}ms`; | ||
spinner.succeed(`Successfully done in ${cyan().bold(elapsed)}`); | ||
|
||
return fetchStatsFromNsecurePayloads(jsonFiles.filter((value) => value !== null)); | ||
} | ||
catch (error) { | ||
spinner.failed(error.message); | ||
throw error; | ||
} | ||
const spinner = new Spinner({ | ||
prefixText: kleur.white().bold("Clone and analyze built-in addons") | ||
}).start("clone repositories..."); | ||
|
||
try { | ||
const repos = await Promise.all(config.git_repositories.map(cloneGITRepository)); | ||
spinner.text = "Run node-secure analyze"; | ||
|
||
const jsonFiles = await Promise.all(repos.map(nsecure.onLocalDirectory)); | ||
const elapsed = `${spinner.elapsedTime.toFixed(2)}ms`; | ||
spinner.succeed(`Successfully done in ${kleur.cyan().bold(elapsed)}`); | ||
|
||
return fetchStatsFromNsecurePayloads(jsonFiles.filter((value) => value !== null)); | ||
} | ||
catch (error) { | ||
spinner.failed(error.message); | ||
throw error; | ||
} | ||
} | ||
|
||
// eslint-disable-next-line max-params | ||
function toChart(baliseName, data, interpolateName, type = "bar") { | ||
const graphLabels = Object.keys(data).map((key) => `"${key}"`).join(","); | ||
const graphLabels = Object.keys(data).map((key) => `"${key}"`).join(","); | ||
|
||
return kChartTemplate(baliseName, graphLabels, Object.values(data).join(","), interpolateName, type); | ||
return kChartTemplate(baliseName, graphLabels, Object.values(data).join(","), interpolateName, type); | ||
} | ||
|
||
function generateChartArray(pkgStats, repoStats) { | ||
const charts = []; | ||
const displayableCharts = config.charts.filter((chart) => chart.display); | ||
|
||
if (pkgStats !== null) { | ||
for (const chart of displayableCharts) { | ||
const name = chart.name.toLowerCase(); | ||
charts.push(toChart(`npm_${name}_canvas`, pkgStats[name], chart.interpolation, chart.type)); | ||
} | ||
const charts = []; | ||
const displayableCharts = config.charts.filter((chart) => chart.display); | ||
|
||
if (pkgStats !== null) { | ||
for (const chart of displayableCharts) { | ||
const name = chart.name.toLowerCase(); | ||
charts.push(toChart(`npm_${name}_canvas`, pkgStats[name], chart.interpolation, chart.type)); | ||
} | ||
if (repoStats !== null) { | ||
for (const chart of displayableCharts) { | ||
const name = chart.name.toLowerCase(); | ||
charts.push(toChart(`git_${name}_canvas`, repoStats[name], chart.interpolation, chart.type)); | ||
} | ||
} | ||
if (repoStats !== null) { | ||
for (const chart of displayableCharts) { | ||
const name = chart.name.toLowerCase(); | ||
charts.push(toChart(`git_${name}_canvas`, repoStats[name], chart.interpolation, chart.type)); | ||
} | ||
} | ||
|
||
return charts; | ||
return charts; | ||
} | ||
|
||
async function main() { | ||
await Promise.all([ | ||
mkdir(kJsonDir, { recursive: true }), | ||
mkdir(kCloneDir, { recursive: true }), | ||
mkdir(kReportsDir, { recursive: true }) | ||
]); | ||
|
||
try { | ||
// eslint-disable-next-line new-cap | ||
const generationDate = Intl.DateTimeFormat("en-GB", { | ||
day: "2-digit", month: "short", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric" | ||
}).format(new Date()); | ||
|
||
const pkgStats = await (config.npm_packages.length === 0 ? Promise.resolve(null) : fetchPackagesStats()); | ||
const repoStats = await (config.git_repositories.length === 0 ? Promise.resolve(null) : fetchRepositoriesStats()); | ||
if (pkgStats === null && repoStats === null) { | ||
console.log("No git repositories and no npm packages to fetch in the local configuration!"); | ||
process.exit(0); | ||
} | ||
|
||
console.log("Start generating template!"); | ||
const HTMLTemplateStr = await readFile(join(kViewsDir, "template.html"), "utf8"); | ||
const templateGenerator = compile(HTMLTemplateStr); | ||
|
||
const templatePayload = { | ||
report_theme: kAvailableThemes.has(config.theme) ? config.theme : "dark", | ||
report_title: config.report_title, | ||
report_logo: config.report_logo, | ||
report_date: generationDate, | ||
npm_stats: pkgStats, | ||
git_stats: repoStats, | ||
charts: config.charts.filter((chart) => chart.display).map(({ name, help = null }) => { | ||
return { name, help }; | ||
}) | ||
}; | ||
|
||
const charts = generateChartArray(pkgStats, repoStats); | ||
const HTMLReport = templateGenerator(templatePayload) | ||
.concat(`\n<script>\ndocument.addEventListener("DOMContentLoaded", () => {\n${charts.join("\n")}\n});\n</script>`); | ||
|
||
const reportHTMLPath = join(kReportsDir, cleanReportName(config.report_title, ".html")); | ||
await writeFile(reportHTMLPath, HTMLReport); | ||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||
console.log("HTML Report writted on disk!"); | ||
|
||
await generatePDF(reportHTMLPath); | ||
console.log("Report sucessfully generated!"); | ||
} | ||
finally { | ||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||
await rmdir(kCloneDir, { recursive: true }); | ||
process.exit(0); | ||
await Promise.all([ | ||
promises.mkdir(kJsonDir, { recursive: true }), | ||
promises.mkdir(kCloneDir, { recursive: true }), | ||
promises.mkdir(kReportsDir, { recursive: true }) | ||
]); | ||
|
||
try { | ||
// eslint-disable-next-line new-cap | ||
const generationDate = Intl.DateTimeFormat("en-GB", { | ||
day: "2-digit", month: "short", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric" | ||
}).format(new Date()); | ||
|
||
const pkgStats = await (config.npm_packages.length === 0 ? Promise.resolve(null) : fetchPackagesStats()); | ||
const repoStats = await (config.git_repositories.length === 0 ? Promise.resolve(null) : fetchRepositoriesStats()); | ||
if (pkgStats === null && repoStats === null) { | ||
console.log("No git repositories and no npm packages to fetch in the local configuration!"); | ||
process.exit(0); | ||
} | ||
|
||
console.log("Start generating template!"); | ||
const HTMLTemplateStr = await promises.readFile(path.join(kViewsDir, "template.html"), "utf8"); | ||
const templateGenerator = compile(HTMLTemplateStr); | ||
|
||
|
||
const templatePayload = { | ||
report_theme: kAvailableThemes.has(config.theme) ? config.theme : "dark", | ||
report_title: config.report_title, | ||
report_logo: config.report_logo, | ||
report_date: generationDate, | ||
npm_stats: pkgStats, | ||
git_stats: repoStats, | ||
charts: config.charts.filter((chart) => chart.display).map(({ name, help = null }) => { | ||
return { name, help }; | ||
}) | ||
}; | ||
|
||
const charts = generateChartArray(pkgStats, repoStats); | ||
|
||
const HTMLReport = templateGenerator(templatePayload) | ||
.concat(`\n<script>\ndocument.addEventListener("DOMContentLoaded", () => {\n${charts.join("\n")}\n});\n</script>`); | ||
|
||
const reportHTMLPath = path.join(kReportsDir, cleanReportName(config.report_title, ".html")); | ||
await promises.writeFile(reportHTMLPath, HTMLReport); | ||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||
console.log("HTML Report writted on disk!"); | ||
|
||
await generatePDF(reportHTMLPath); | ||
console.log("Report sucessfully generated!"); | ||
} | ||
finally { | ||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||
await promises.rm(kCloneDir, { recursive: true }); | ||
process.exit(0); | ||
} | ||
} | ||
main().catch(console.error); | ||
|
Oops, something went wrong.