Future getScoreCardData()

in app/lib/scorecard/backend.dart [113:179]


  Future<ScoreCardData?> getScoreCardData(
    String packageName,
    String? packageVersion, {
    bool onlyCurrent = false,
  }) async {
    final requiredReportTypes = ReportType.values;
    if (packageVersion == null || packageVersion == 'latest') {
      final key = _db.emptyKey.append(Package, id: packageName);
      final p = await _db.lookupOrNull<Package>(key);
      if (p == null) {
        return null;
      }
      packageVersion = p.latestVersion;
    }
    final cached = onlyCurrent
        ? null
        : await cache.scoreCardData(packageName, packageVersion!).get();
    if (cached != null && cached.hasReports(requiredReportTypes)) {
      return cached;
    }

    final key = scoreCardKey(packageName, packageVersion!);
    final current = (await _db.lookupOrNull<ScoreCard>(key))?.toData();
    if (current != null) {
      // only full cards will be stored in cache
      if (current.isCurrent && current.hasReports(ReportType.values)) {
        await cache.scoreCardData(packageName, packageVersion).set(current);
      }
      if (onlyCurrent || current.hasReports(requiredReportTypes)) {
        return current;
      }
    }

    if (onlyCurrent) return null;

    // List cards that at minimum have a pana report.
    final fallbackKeys = versions.fallbackRuntimeVersions
        .map((v) =>
            scoreCardKey(packageName, packageVersion!, runtimeVersion: v))
        .toList();
    final fallbackCards = await _db.lookup<ScoreCard>(fallbackKeys);
    final fallbackCardData =
        fallbackCards.where((c) => c != null).map((c) => c!.toData()).toList();

    if (fallbackCardData.isEmpty) return null;

    final fallbackCard = fallbackCardData
            .firstWhereOrNull((d) => d.hasReports(requiredReportTypes)) ??
        fallbackCardData
            .firstWhereOrNull((d) => d.hasReports([ReportType.pana]));

    // For recently uploaded version, we don't want to fallback to an analysis
    // coming from an older running deployment too early. A new analysis may
    // come soon from the current runtime, and if it is different in significant
    // ways (e.g. score or success status differs), it may confuse users looking
    // at it in the interim period.
    //
    // However, once the upload is above the specified age, it is better to
    // display and old analysis than to keep waiting on a new one.
    if (fallbackCard != null) {
      final age = clock.now().difference(fallbackCard.packageVersionCreated!);
      if (age < _fallbackMinimumAge) {
        return null;
      }
    }
    return fallbackCard;
  }