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;
  // Get the tarball URL from the version metadata.
  final metaUri = Uri.parse('$base/$package/$version');
  final metaResp = await _http.get(metaUri, headers: headers);
  if (metaResp.statusCode != 200) {
    throw StateError(
      'npm: failed to fetch metadata for $package@$version: '
      '${metaResp.statusCode}',
    );
  }
  final meta = jsonDecode(metaResp.body) as Map<String, dynamic>;
  final dist = meta['dist'] as Map<String, dynamic>? ?? {};
  final tarballUrl =
      dist['tarball'] as String? ?? '$base/$package/-/$package-$version.tgz';

  final response = await _http.get(Uri.parse(tarballUrl), headers: headers);
  if (response.statusCode != 200) {
    throw StateError(
      'npm: failed to download $package@$version: ${response.statusCode}',
    );
  }

  final decompressed = GZipDecoder().decodeBytes(response.bodyBytes);
  final tarArchive = TarDecoder().decodeBytes(decompressed);

  final targets = modulePath != null
      ? [modulePath, 'package/$modulePath']
      : ['package/module.ball.bin', 'package/module.ball.json'];

  for (final target in targets) {
    for (final file in tarArchive) {
      if (!file.isFile) continue;
      if (file.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: tarballUrl,
        );
      }
    }
  }
  throw StateError(
    'npm: Ball module not found in $package@$version. '
    'Looked for: ${targets.join(", ")}',
  );
}