scan method
Scans the project at projectRoot and returns a report.
Implementation
Future<ScanReport> scan({
required String projectRoot,
String? configPath,
required bool includeTransitive,
}) async {
final DepSherpaConfig config =
configService.load(configPath: configPath, projectRoot: projectRoot);
final ProjectManifest manifest = pubspecService.load(
projectRoot,
seedIdentity: config.project,
);
final DependencySnapshot snapshot = await depsService.inspect(
projectRoot: projectRoot,
manifest: manifest,
);
final Map<String, DependencyGraphMetrics> graphMetrics =
graphService.analyze(snapshot.nodes);
final List<DependencyRiskEntry> entries = <DependencyRiskEntry>[];
for (final DependencyNode node in snapshot.nodes.values) {
if (!includeTransitive && !node.isDirect) {
continue;
}
PackageHealth health = await pubApiService.fetch(node.name, config);
health = await githubService.enrich(health, config);
final DependencyProfile profile = DependencyProfile(
node: node,
metrics: graphMetrics[node.name] ??
const DependencyGraphMetrics(
maxDepth: 0,
transitiveCount: 0,
directDependents: 0,
paths: <List<String>>[],
centrality: 0,
),
health: health,
);
final RiskScore score = scoringService.score(
dependency: profile,
project: manifest,
config: config,
);
entries.add(DependencyRiskEntry(dependency: profile, riskScore: score));
}
final GraphSummary graph = graphService.summarize(snapshot.nodes);
final List<DependencyRiskEntry> ranked =
List<DependencyRiskEntry>.from(entries)
..sort((DependencyRiskEntry a, DependencyRiskEntry b) {
return b.riskScore.finalScore.compareTo(a.riskScore.finalScore);
});
final double overallScore = ranked.isEmpty
? 0
: ranked
.map((DependencyRiskEntry entry) => entry.riskScore.finalScore)
.reduce((double a, double b) => a + b) /
ranked.length;
return ScanReport(
generatedAt: DateTime.now().toUtc(),
projectName: manifest.name,
projectVersion: manifest.version,
rootPath: p.normalize(projectRoot),
includeTransitive: includeTransitive,
offline: config.network.offline,
graph: graph,
dependencies: ranked,
overallScore: overallScore,
summary: <String, Object?>{
'dependencyCount': ranked.length,
'highRiskCount': ranked
.where((DependencyRiskEntry entry) => entry.riskScore.isHighRisk)
.length,
'criticalCount': ranked.where((DependencyRiskEntry entry) {
return entry.riskScore.classification == RiskClassification.critical;
}).length,
'generatedFrom': <String, Object?>{
'pubspec': p.join(projectRoot, 'pubspec.yaml'),
'lockfile': p.join(projectRoot, 'pubspec.lock'),
'depsCommand': manifest.usesFlutter
? 'flutter pub deps --json'
: 'dart pub deps --json',
},
},
);
}