blob: c24ec429f8a336100e9432801610cefcbea32aeb [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:pub_semver/pub_semver.dart';
/// Finding version of [package] that is published on pub.
class PubVersionFinder {
/// Constructor.
///
/// Note: you should manually close the [httpClient] when done using the finder.
PubVersionFinder({this.pubHost = defaultPubHost, required this.httpClient});
/// The default pub host to use.
static const String defaultPubHost = 'https://pub.dev';
/// The pub host url, defaults to `https://pub.dev`.
final String pubHost;
/// The http client.
///
/// You should manually close this client when done using this finder.
final http.Client httpClient;
/// Get the package version on pub.
Future<PubVersionFinderResponse> getPackageVersion(
{required String packageName}) async {
assert(packageName.isNotEmpty);
final Uri pubHostUri = Uri.parse(pubHost);
final Uri url = pubHostUri.replace(path: '/packages/$packageName.json');
final http.Response response = await httpClient.get(url);
if (response.statusCode == 404) {
return PubVersionFinderResponse(
versions: <Version>[],
result: PubVersionFinderResult.noPackageFound,
httpResponse: response);
} else if (response.statusCode != 200) {
return PubVersionFinderResponse(
versions: <Version>[],
result: PubVersionFinderResult.fail,
httpResponse: response);
}
final Map<Object?, Object?> responseBody =
json.decode(response.body) as Map<Object?, Object?>;
final List<Version> versions = (responseBody['versions']! as List<Object?>)
.cast<String>()
.map<Version>(
(final String versionString) => Version.parse(versionString))
.toList();
return PubVersionFinderResponse(
versions: versions,
result: PubVersionFinderResult.success,
httpResponse: response);
}
}
/// Represents a response for [PubVersionFinder].
class PubVersionFinderResponse {
/// Constructor.
PubVersionFinderResponse(
{required this.versions,
required this.result,
required this.httpResponse}) {
if (versions.isNotEmpty) {
versions.sort((Version a, Version b) {
// TODO(cyanglaz): Think about how to handle pre-release version with [Version.prioritize].
// https://github.com/flutter/flutter/issues/82222
return b.compareTo(a);
});
}
}
/// The versions found in [PubVersionFinder].
///
/// This is sorted by largest to smallest, so the first element in the list is the largest version.
/// Might be `null` if the [result] is not [PubVersionFinderResult.success].
final List<Version> versions;
/// The result of the version finder.
final PubVersionFinderResult result;
/// The response object of the http request.
final http.Response httpResponse;
}
/// An enum representing the result of [PubVersionFinder].
enum PubVersionFinderResult {
/// The version finder successfully found a version.
success,
/// The version finder failed to find a valid version.
///
/// This might due to http connection errors or user errors.
fail,
/// The version finder failed to locate the package.
///
/// This indicates the package is new.
noPackageFound,
}