From 3acbf6d545536c3440d508dae070c1bd59f7dc9a Mon Sep 17 00:00:00 2001 From: Pierre Demailly Date: Tue, 1 Jul 2025 19:25:52 +0200 Subject: [PATCH] feat(interface): module types --- i18n/english.js | 2 ++ i18n/french.js | 4 ++- package.json | 2 +- .../package/pannels/overview/overview.js | 6 +++- public/components/views/home/home.html | 7 +++++ public/components/views/home/home.js | 28 +++++++++++++++++++ workspaces/server/src/config.ts | 2 +- 7 files changed, 47 insertions(+), 4 deletions(-) diff --git a/i18n/english.js b/i18n/english.js index d08251c0..7ad9f000 100644 --- a/i18n/english.js +++ b/i18n/english.js @@ -128,6 +128,7 @@ const ui = { tsTypings: "TS Typings", node: "Node.js Compatibility", npm: "NPM Compatibility", + type: "Module type", lastReleaseVersion: "Last release version", lastReleaseDate: "Last release date", publishedReleases: "Number of published releases", @@ -174,6 +175,7 @@ const ui = { }, watch: "Packages in the dependency tree requiring greater attention", criticalWarnings: "Critical Warnings", + moduleTypes: "Module Types", maintainers: "Maintainers", showMore: "show more", showLess: "show less" diff --git a/i18n/french.js b/i18n/french.js index 8a070902..72497141 100644 --- a/i18n/french.js +++ b/i18n/french.js @@ -81,7 +81,7 @@ const cli = { startHttp: { invalidScannerVersion: tS`le fichier d'analyse correspond à la version '${0}' du scanner et ne satisfait pas la range '${1}' attendu par la CLI`, regenerate: "veuillez re-générer un nouveau fichier d'analyse JSON en utilisant votre CLI" - }, + } }; const ui = { @@ -128,6 +128,7 @@ const ui = { tsTypings: "Typages TS", node: "Compatibilité Node.js", npm: "Compatibilité NPM", + type: "Type de module", lastReleaseVersion: "Dernière version publiée", lastReleaseDate: "Date de la dernière version", publishedReleases: "Nombre de versions publiées", @@ -174,6 +175,7 @@ const ui = { }, watch: "Packages dans l'arbre de dépendance nécessitant une plus grande attention", criticalWarnings: "Avertissements critiques", + moduleTypes: "Types de modules", maintainers: "Mainteneurs", showMore: "voir plus", showLess: "voir moins" diff --git a/package.json b/package.json index d9a9615e..22f2f68d 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "@nodesecure/documentation-ui": "^1.3.0", "@nodesecure/flags": "^3.0.3", "@nodesecure/i18n": "^4.0.1", - "@nodesecure/js-x-ray": "^9.0.0", + "@nodesecure/js-x-ray": "^9.2.0", "@nodesecure/licenses-conformance": "^2.1.0", "@nodesecure/npm-registry-sdk": "^3.0.0", "@nodesecure/ossf-scorecard-sdk": "^3.2.1", diff --git a/public/components/package/pannels/overview/overview.js b/public/components/package/pannels/overview/overview.js index 809a98bc..18d2c799 100644 --- a/public/components/package/pannels/overview/overview.js +++ b/public/components/package/pannels/overview/overview.js @@ -127,7 +127,7 @@ export class Overview { } renderTopFields() { - const { size, composition, engines = {} } = this.package.dependencyVersion; + const { size, composition, engines = {}, type } = this.package.dependencyVersion; const { metadata } = this.package.dependency; const fragment = document.createDocumentFragment(); @@ -168,6 +168,10 @@ export class Overview { )); } + fragment.appendChild(utils.createLiField( + i18n.package_info.overview.type, type + )); + return fragment; } diff --git a/public/components/views/home/home.html b/public/components/views/home/home.html index f2763205..8b5e4932 100644 --- a/public/components/views/home/home.html +++ b/public/components/views/home/home.html @@ -50,6 +50,13 @@
+
+
+ +

[[=z.token('home.moduleTypes')]]

+
+
+
diff --git a/public/components/views/home/home.js b/public/components/views/home/home.js index 14b80b1e..db9cfb0a 100644 --- a/public/components/views/home/home.js +++ b/public/components/views/home/home.js @@ -54,6 +54,7 @@ export class HomeView { this.generateExtensions(); this.generateLicenses(); this.generateMaintainers(); + this.generateModuleTypes(); this.handleReport(); } @@ -316,6 +317,33 @@ export class HomeView { .render(); } + generateModuleTypes() { + const moduleTypesElement = document.getElementById("home-modules-types"); + const moduleTypes = Object.values(this.secureDataSet.data.dependencies).reduce((acc, dep) => { + const types = Object.values(dep.versions).map((version) => version.type); + for (const type of types) { + acc[type] += 1; + } + + return acc; + }, { + esm: 0, + cjs: 0, + dual: 0, + dts: 0, + faux: 0 + }); + const moduleTypesJaugeData = [...Object.entries(moduleTypes)] + .sort(([, left], [, right]) => right - left) + .map(([name, value]) => { + return { name, value }; + }); + + moduleTypesElement.appendChild( + new Gauge(moduleTypesJaugeData).render() + ); + } + async generateDownloads() { const homeOverviewElement = document.querySelector(".home--overview"); const { name } = this.secureDataSet.linker.get(0); diff --git a/workspaces/server/src/config.ts b/workspaces/server/src/config.ts index 9e88f3d6..b4051533 100644 --- a/workspaces/server/src/config.ts +++ b/workspaces/server/src/config.ts @@ -6,7 +6,7 @@ import { appCache, type AppConfig } from "@nodesecure/cache"; import { logger } from "./logger.js"; const experimentalWarnings = Object.entries(warnings) - .flatMap(([warning, { experimental }]) => (experimental ? [warning] : [])) as WarningName[]; + .flatMap(([warning, metadata]) => ("experimental" in metadata && metadata.experimental ? [warning] : [])) as WarningName[]; // CONSTANTS const kDefaultConfig = {