diff --git a/package.json b/package.json index e54daf10..cc92e191 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,7 @@ "scripts": { "test": "node --test", "validate": "node tools/vuln_valid", - "create-npm-index": "node tools/create_index/create_npm_index.js", - "create-core-index": "node tools/create_index/create_core_index.js", - "create-deps-index": "node tools/create_index/create_deps_index.js" - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - "@pkgjs/nv": "^0.2.1", - "joi": "^17.13.3", - "semver": "^7.3.8" + "create-npm-index": "node tools/create_index/", + "report-metrics": "node tools/report_metrics.js" } } diff --git a/tests/report_metrics.test.js b/tests/report_metrics.test.js new file mode 100644 index 00000000..7692d69e --- /dev/null +++ b/tests/report_metrics.test.js @@ -0,0 +1,16 @@ +const { test } = require('node:test'); +const assert = require('assert'); +const { computeReporterMetrics } = require('../tools/report_metrics'); + +test('computeReporterMetrics aggregates reporter counts', async () => { + const sampleIndex = [ + { id: 1, reporter: 'alice' }, + { id: 2, reporter: 'bob' }, + { id: 3, reporter: 'alice' }, + { id: 4, reporter: 'charlie' }, + { id: 5, reporter: 'bob' }, + ]; + + const metrics = await computeReporterMetrics(sampleIndex); + assert.deepStrictEqual(metrics, { alice: 2, bob: 2, charlie: 1 }); +}); diff --git a/tools/report_metrics.js b/tools/report_metrics.js new file mode 100644 index 00000000..800f308b --- /dev/null +++ b/tools/report_metrics.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node +/** + * Compute reporter metrics from a vulnerability index. + * + * The index is expected to be a JSON array of vulnerability objects. + * Each vulnerability may contain a `reporter`, `reporter_name`, + * `reporterId`, or `reporter_id` field. The script aggregates the + * number of reports per reporter and outputs a JSON object mapping + * reporter identifiers to counts. + * + * Usage: + * node tools/report_metrics.js [index-file] + * + * If no index-file is provided, it defaults to `tools/vuln_index.json`. + */ + +const fs = require('fs').promises; +const path = require('path'); + +/** + * Compute reporter metrics from an array of vulnerability objects. + * + * @param {Array} indexData - Array of vulnerability objects. + * @returns {Object} Mapping of reporter to count. + */ +async function computeReporterMetrics(indexData) { + const metrics = new Map(); + + for (const vuln of indexData) { + const reporter = + vuln.reporter || + vuln.reporter_name || + vuln.reporterId || + vuln.reporter_id; + + if (!reporter) continue; + + metrics.set(reporter, (metrics.get(reporter) || 0) + 1); + } + + return Object.fromEntries(metrics); +} + +/** + * Main entry point for the CLI. + */ +async function main() { + const indexPath = + process.argv[2] ?? path.resolve('tools', 'vuln_index.json'); + + const data = await fs.readFile(indexPath, 'utf8'); + const index = JSON.parse(data); + + const metrics = await computeReporterMetrics(index); + console.log(JSON.stringify(metrics, null, 2)); +} + +if (require.main === module) { + main().catch((err) => { + console.error(err); + process.exit(1); + }); +} + +module.exports = { computeReporterMetrics };