checkContract function

ContractReport checkContract(
  1. Map<String, dynamic> pinned,
  2. Map<String, dynamic> current
)

Compares pinned against current, both decoded routes.json payloads.

Implementation

ContractReport checkContract(
  Map<String, dynamic> pinned,
  Map<String, dynamic> current,
) {
  final changes = <ContractChange>[];

  final pinnedVersion = pinned['version'] as int? ?? 0;
  final currentVersion = current['version'] as int? ?? 0;

  // Version 1 has no `returns`, so absent must not be read as "unchanged" —
  // that would report a clean check for a comparison it cannot make.
  final canCompareReturns = pinnedVersion >= 2 && currentVersion >= 2;
  if (!canCompareReturns) {
    changes.add(
      const ContractChange(
        severity: ContractSeverity.compatible,
        route: 'manifest',
        description:
            'return types not compared: one side predates manifest version 2. '
            'Re-pin against a current manifest to include them.',
      ),
    );
  }

  final pinnedRoutes = _byKey(pinned);
  final currentRoutes = _byKey(current);

  for (final MapEntry(key: key, value: before) in pinnedRoutes.entries) {
    final after = currentRoutes[key];

    if (after == null) {
      changes.add(
        ContractChange(
          severity: ContractSeverity.breaking,
          route: key,
          description: 'route removed',
        ),
      );
      continue;
    }

    changes.addAll(
      _compareRoute(key, before, after, canCompareReturns: canCompareReturns),
    );
  }

  for (final key in currentRoutes.keys) {
    if (!pinnedRoutes.containsKey(key)) {
      // Additive: nothing the consumer already calls is affected.
      changes.add(
        ContractChange(
          severity: ContractSeverity.compatible,
          route: key,
          description: 'route added',
        ),
      );
    }
  }

  return ContractReport(changes);
}