fromJson static method
Parses a decoded package_graph.json value.
Throws FormatException if the file is not a valid package graph file.
Implementation
static PackageGraph fromJson(final Object? json) {
if (json is! Map) {
throw const FormatException(
'Expected package_graph.json top level to be a map',
);
}
final map = Map<String, dynamic>.from(json);
if (map['configVersion'] != _supportedConfigVersion) {
throw FormatException(
'Unsupported package_graph.json configVersion: '
'${map['configVersion']}',
);
}
final rootNames = _parseStringList(map, 'roots');
final packagesJson = map['packages'];
if (packagesJson is! List) {
throw const FormatException('Expected `packages` to be a list');
}
final packagesByName = <String, PgPackage>{};
final dependencyNamesByPackage = <String, List<String>>{};
final devDependencyNamesByPackage = <String, List<String>>{};
for (final entry in packagesJson) {
if (entry is! Map) {
throw const FormatException('Expected each package to be a map');
}
final packageMap = Map<String, dynamic>.from(entry);
final name = packageMap['name'];
if (name is! String) {
throw const FormatException('Expected package `name` to be a string');
}
final version = packageMap['version'];
if (version is! String) {
throw const FormatException(
'Expected package `version` to be a string',
);
}
packagesByName[name] = PgPackage(
name: name,
version: version,
dependencies: [],
devDependencies: [],
references: [],
devReferences: [],
);
dependencyNamesByPackage[name] = _parseStringList(
packageMap,
'dependencies',
);
devDependencyNamesByPackage[name] = _parseStringList(
packageMap,
'devDependencies',
);
}
for (final MapEntry(key: name, value: package) in packagesByName.entries) {
final dependencyNames = dependencyNamesByPackage[name];
if (dependencyNames == null) {
throw FormatException('Missing dependency list for package "$name"');
}
for (final depName in dependencyNames) {
final dependency = packagesByName[depName];
if (dependency == null) {
throw FormatException(
'Package "$name" depends on unknown package "$depName"',
);
}
package.dependencies.add(dependency);
dependency.references.add(package);
}
final devDependencyNames = devDependencyNamesByPackage[name];
if (devDependencyNames == null) {
throw FormatException('Missing devDependency list for package "$name"');
}
for (final depName in devDependencyNames) {
final dependency = packagesByName[depName];
if (dependency == null) {
throw FormatException(
'Package "$name" has unknown dev dependency "$depName"',
);
}
package.devDependencies.add(dependency);
dependency.devReferences.add(package);
}
}
final roots = <PgPackage>[];
for (final rootName in rootNames) {
final root = packagesByName[rootName];
if (root == null) {
throw FormatException('Unknown root package "$rootName"');
}
roots.add(root);
}
return PackageGraph(roots: roots);
}