Built-in reporter plugins for generating statistics and custom output formats.
Generate detailed statistics about module dependencies and project structure.
/**
* Sample statistics reporter plugin that analyzes dependency patterns
* @param cruiseResult - Analysis result from cruise function
* @returns Reporter output with dependency statistics in JSON format
*/
import statsPlugin from "dependency-cruiser/sample-reporter-plugin";
type StatsReporterPlugin = (cruiseResult: ICruiseResult) => IReporterOutput;Usage Examples:
import { cruise, format } from "dependency-cruiser";
import statsPlugin from "dependency-cruiser/sample-reporter-plugin";
// Get analysis results
const cruiseResult = await cruise(["src"]);
// Generate statistics using plugin directly
const stats = statsPlugin(cruiseResult.output);
console.log(JSON.parse(stats.output));
// Or use via format function
const statsReport = await format(cruiseResult.output, {
outputType: "plugin:stats-reporter-plugin.js"
});Statistics Generated:
{
"moduleCount": 150,
"dependencyCount": 423,
"minDependenciesPerModule": 0,
"maxDependenciesPerModule": 15,
"meanDependenciesPerModule": 2.82,
"medianDependenciesPerModule": 2,
"p75DependenciesPerModule": 4,
"minDependentsPerModule": 0,
"maxDependentsPerModule": 8,
"meanDependentsPerModule": 2.82,
"medianDependentsPerModule": 2,
"p75DependentsPerModule": 4
}Generate Mermaid diagrams for dependency visualization.
/**
* Mermaid reporter plugin that creates flowchart diagrams
* @param cruiseResult - Analysis result from cruise function
* @returns Reporter output with Mermaid diagram syntax
*/
import mermaidPlugin from "dependency-cruiser/mermaid-reporter-plugin";
type MermaidReporterPlugin = (cruiseResult: ICruiseResult) => IReporterOutput;Usage Examples:
import { cruise, format } from "dependency-cruiser";
// Generate Mermaid diagram via format
const mermaidDiagram = await format(cruiseResult.output, {
outputType: "mermaid",
collapse: 2,
includeOnly: "^src/"
});
// Write to file for use in documentation
import fs from "fs/promises";
await fs.writeFile("dependency-graph.md", `
# Dependency Graph
\`\`\`mermaid
${mermaidDiagram.output}
\`\`\`
`);
// Or use plugin directly
import mermaidPlugin from "dependency-cruiser/mermaid-reporter-plugin";
const diagram = mermaidPlugin(cruiseResult.output);Generate 3D visualization data for dependency graphs.
/**
* 3D visualization reporter plugin
* @param cruiseResult - Analysis result from cruise function
* @returns Reporter output with 3D visualization data
*/
import threeDPlugin from "dependency-cruiser/sample-3d-reporter-plugin";
type ThreeDReporterPlugin = (cruiseResult: ICruiseResult) => IReporterOutput;Usage Examples:
import threeDPlugin from "dependency-cruiser/sample-3d-reporter-plugin";
// Generate 3D visualization data
const threeDData = threeDPlugin(cruiseResult.output);
// Use with 3D visualization libraries
const visualizationData = JSON.parse(threeDData.output);
// Process with Three.js, D3.js, or other 3D librariesCreate custom reporter plugins for specialized output formats.
/**
* Reporter plugin function signature
* @param cruiseResult - Complete analysis results
* @returns Object with output string and exit code
*/
type ReporterPlugin = (cruiseResult: ICruiseResult) => IReporterOutput;
interface IReporterOutput {
/** Generated output (usually string, but can be structured data) */
output: string | ICruiseResult;
/** Exit code - 0 for success, non-zero for errors/violations found */
exitCode: number;
}Custom Plugin Example:
// custom-csv-reporter.js
function customCsvReporter(cruiseResult) {
const headers = ["source", "target", "circular", "dynamic", "dependencyTypes"];
const rows = [headers.join(",")];
cruiseResult.modules.forEach(module => {
module.dependencies.forEach(dep => {
const row = [
module.source,
dep.resolved,
dep.circular,
dep.dynamic,
dep.dependencyTypes.join(";")
];
rows.push(row.join(","));
});
});
return {
output: rows.join("\n"),
exitCode: cruiseResult.summary.error > 0 ? 1 : 0
};
}
export default customCsvReporter;Using Custom Plugin:
import { format } from "dependency-cruiser";
import customCsvReporter from "./custom-csv-reporter.js";
// Use plugin directly
const csvReport = customCsvReporter(cruiseResult.output);
// Or register and use via format
const csvReport = await format(cruiseResult.output, {
outputType: "plugin:./custom-csv-reporter.js"
});Common patterns for integrating reporter plugins into workflows.
Build Process Integration:
// build-integration.js
import { cruise } from "dependency-cruiser";
import statsPlugin from "dependency-cruiser/sample-reporter-plugin";
async function generateBuildMetrics() {
const result = await cruise(["src"]);
// Generate statistics
const stats = statsPlugin(result.output);
const metrics = JSON.parse(stats.output);
// Fail build if metrics exceed thresholds
if (metrics.maxDependenciesPerModule > 10) {
console.error("Module complexity too high!");
process.exit(1);
}
// Save metrics for tracking
await fs.writeFile(
"build-metrics.json",
JSON.stringify({
timestamp: new Date().toISOString(),
...metrics
}, null, 2)
);
}Documentation Generation:
// doc-generation.js
async function generateDocumentation() {
const result = await cruise(["src"]);
// Generate multiple formats
const [htmlReport, mermaidDiagram, stats] = await Promise.all([
format(result.output, { outputType: "html" }),
format(result.output, { outputType: "mermaid", collapse: 2 }),
format(result.output, { outputType: "plugin:stats-reporter-plugin.js" })
]);
// Write documentation files
await Promise.all([
fs.writeFile("docs/dependency-report.html", htmlReport.output),
fs.writeFile("docs/architecture.md", `
# Architecture Overview
## Dependency Graph
\`\`\`mermaid
${mermaidDiagram.output}
\`\`\`
## Statistics
${JSON.stringify(JSON.parse(stats.output), null, 2)}
`),
]);
}Configure plugin behavior through cruise and format options.
Mermaid Plugin Configuration:
// Mermaid with custom styling and filtering
const mermaidOutput = await format(result.output, {
outputType: "mermaid",
// Focus on specific areas
focus: "src/core",
// Collapse for better overview
collapse: "^src/[^/]+/",
// Exclude test files
exclude: ["test/", "*.test.js"],
// Only show local dependencies
includeOnly: { dependencyTypes: ["local"] }
});Statistics Plugin with Filtering:
// Get statistics for specific subset
const filteredResult = {
...cruiseResult.output,
modules: cruiseResult.output.modules.filter(
module => module.source.startsWith("src/core")
)
};
const coreStats = statsPlugin(filteredResult);Proper error handling and exit code management in reporter plugins.
Plugin with Error Handling:
function robustReporter(cruiseResult) {
try {
// Plugin logic here
const output = generateReport(cruiseResult);
// Determine exit code based on violations
const hasErrors = cruiseResult.summary.error > 0;
const hasWarnings = cruiseResult.summary.warn > 0;
return {
output,
exitCode: hasErrors ? 2 : hasWarnings ? 1 : 0
};
} catch (error) {
return {
output: `Error in reporter plugin: ${error.message}`,
exitCode: 3
};
}
}Optimize plugin performance for large codebases.
Efficient Plugin Implementation:
function efficientStatsPlugin(cruiseResult) {
// Use single pass for multiple calculations
let totalDeps = 0;
let maxDeps = 0;
let minDeps = Infinity;
const depCounts = [];
cruiseResult.modules.forEach(module => {
const depCount = module.dependencies.length;
totalDeps += depCount;
maxDeps = Math.max(maxDeps, depCount);
minDeps = Math.min(minDeps, depCount);
depCounts.push(depCount);
});
// Sort once for percentile calculations
depCounts.sort((a, b) => a - b);
const moduleCount = cruiseResult.modules.length;
const medianIndex = Math.floor(moduleCount * 0.5);
const p75Index = Math.floor(moduleCount * 0.75);
return {
output: JSON.stringify({
moduleCount,
dependencyCount: totalDeps,
minDependenciesPerModule: minDeps === Infinity ? 0 : minDeps,
maxDependenciesPerModule: maxDeps,
meanDependenciesPerModule: totalDeps / moduleCount,
medianDependenciesPerModule: depCounts[medianIndex] || 0,
p75DependenciesPerModule: depCounts[p75Index] || 0
}, null, 2),
exitCode: 0
};
}Test reporter plugins to ensure correct behavior.
Plugin Test Example:
// test-plugin.js
import assert from "assert";
import statsPlugin from "dependency-cruiser/sample-reporter-plugin";
function testStatsPlugin() {
const mockCruiseResult = {
modules: [
{ source: "a.js", dependencies: [{}, {}] },
{ source: "b.js", dependencies: [{}] },
{ source: "c.js", dependencies: [] }
],
summary: { totalCruised: 3, totalDependenciesCruised: 3 }
};
const result = statsPlugin(mockCruiseResult);
const stats = JSON.parse(result.output);
assert.equal(stats.moduleCount, 3);
assert.equal(stats.dependencyCount, 3);
assert.equal(stats.maxDependenciesPerModule, 2);
assert.equal(stats.minDependenciesPerModule, 0);
console.log("Stats plugin test passed");
}
testStatsPlugin();