fetchModule method
Future<ResolvedRegistryModule>
fetchModule(
- String package,
- String version, {
- String? modulePath,
- ModuleEncoding encoding = ModuleEncoding.MODULE_ENCODING_UNSPECIFIED,
- String? registryUrl,
- Map<
String, String> ? headers,
override
Download the package archive and extract the Ball module bytes.
Implementation
@override
Future<ResolvedRegistryModule> fetchModule(
String package,
String version, {
String? modulePath,
ModuleEncoding encoding = ModuleEncoding.MODULE_ENCODING_UNSPECIFIED,
String? registryUrl,
Map<String, String>? headers,
}) async {
final base = registryUrl ?? defaultUrl;
// pub.flutter-io.cn archive URL: /api/archives/<package>-<version>.tar.gz
// NOT /api/packages/<package>/versions/<version>/archive (returns 404).
final archiveUrl = '$base/api/archives/$package-$version.tar.gz';
final response = await _http.get(Uri.parse(archiveUrl), headers: headers);
if (response.statusCode != 200) {
throw StateError(
'pub: Ball module not found in $package@$version (archive: ${response.statusCode})',
);
}
final decompressed = GZipDecoder().decodeBytes(response.bodyBytes);
final tarArchive = TarDecoder().decodeBytes(decompressed);
final targets = modulePath != null
? [modulePath]
: ['lib/module.ball.bin', 'lib/module.ball.json'];
for (final target in targets) {
for (final file in tarArchive) {
if (!file.isFile) continue;
// pub archives have a top-level directory; strip it.
final name = file.name.contains('/')
? file.name.substring(file.name.indexOf('/') + 1)
: file.name;
if (name == target) {
final enc = target.endsWith('.bin') || target.endsWith('.ball')
? ModuleEncoding.MODULE_ENCODING_PROTO
: ModuleEncoding.MODULE_ENCODING_JSON;
return ResolvedRegistryModule(
bytes: file.content as List<int>,
encoding: enc,
resolvedVersion: version,
sourceUrl: archiveUrl,
);
}
}
}
throw StateError(
'pub: Ball module not found in $package@$version. '
'Looked for: ${targets.join(", ")}',
);
}