const qs = require('node:querystring');
const path = require('node:path');
const include = require('./include.js');
/**
* @module pete/lib/getReporters
*/
module.exports = getReporters;
/**
* Cache of currently open reporters.
* Every key is a name passed to load reporter (name may contain file path and optional querystring).
* Every value is a report function created by specific reporter's factory function.
*
* @private
*/
const CACHE = new Map();
/**
* Build and output data to all reporters.
* If input data already contains a `.report`, just pass that through, without building new one.
*
* @callback report
* @param {Error|null} err
* @param {module:pete/lib/createReport~Report} data to report
*/
/**
* Load reporters and return a function that will pass every report to each of them.
*
* @alias module:pete/lib/getReporters
* @param {string|Array<string>} names
* @param {object} [options]
* @param {boolean} [options.close] set to close specified reporters
* @return {module:pete/lib/getReporters~report|null}
*/
function getReporters (names, options) {
if (!names) {
names = Array.from(CACHE.keys());
}
else if (typeof names === 'string') {
names = [names];
}
else if (!Array.isArray(names)) {
return null;
}
var list = names.reduce((result, name) => {
var reporter = loadReporter(name, options);
if (reporter) {
result.push(reporter);
}
return result;
}, []);
/**
* @type {module:pete/lib/getReporters~report}
*/
return function report (err, data) {
for (var i = 0, max = list.length; i < max; i++) {
list[i](err, data);
}
if (!err && !data && list.length) {
// Closed reporters are not needed anymore
list = [];
}
};
}
/**
* @private
* @param {string|Function} name
* @param {object} options
* @return {Function|boolean}
*/
function loadReporter (name, options) {
var filename;
var cached = CACHE.get(name);
if (cached) {
if (options && options.close) {
cached();
CACHE.delete(name);
}
return cached;
}
if (typeof name === 'function') {
CACHE.set(name, name);
return name;
}
[filename, options] = name.split('?');
if (options) {
options = qs.parse(options);
}
var factory = include(`./reporters/${path.basename(filename)}`) || include(filename);
if (!factory) {
console.error(`Reporter not found: ${name}`);
return false;
}
if (typeof factory !== 'function') {
console.error(`Reporter "${name}" does not export a function and will be ignored`);
return false;
}
var report = factory(options);
if (typeof report !== 'function') {
console.error(`Reporter "${name}" did not create reporting function and will be ignored`);
return false;
}
CACHE.set(name, report);
return report;
}