fetchModule method

  1. @override
Future<ResolvedRegistryModule> fetchModule(
  1. String package,
  2. String version, {
  3. String? modulePath,
  4. ModuleEncoding encoding = ModuleEncoding.MODULE_ENCODING_UNSPECIFIED,
  5. String? registryUrl,
  6. 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(", ")}',
  );
}