reportRouteConflicts function

void reportRouteConflicts(
  1. RouteConfiguration configuration, {
  2. void onViolationStart()?,
  3. OnRouteConflict? onRouteConflict,
  4. void onViolationEnd()?,
})

Reports existence of route conflicts on a RouteConfiguration.

Implementation

void reportRouteConflicts(
  RouteConfiguration configuration, {
  /// Callback called when any route conflict is found.
  void Function()? onViolationStart,

  /// Callback called for each route conflict found.
  OnRouteConflict? onRouteConflict,

  /// Callback called when any route conflict is found.
  void Function()? onViolationEnd,
}) {
  final directConflicts = configuration.endpoints.entries
      .where((entry) => entry.value.length > 1)
      .map((e) => _RouteConflict(e.value.first.path, e.value.last.path, e.key));

  final indirectConflicts = configuration.endpoints.entries
      .map((entry) {
        final matches = configuration.endpoints.keys.where((other) {
          final keyParts = entry.key.split('/');
          if (other == entry.key) {
            return false;
          }

          final otherParts = other.split('/');

          var match = false;

          if (keyParts.length == otherParts.length) {
            for (var i = 0; i < keyParts.length; i++) {
              if ((keyParts[i] == otherParts[i]) ||
                  (keyParts[i].startsWith('<') ||
                      otherParts[i].startsWith('<'))) {
                match = true;
              } else {
                match = false;
                break;
              }
            }
          }

          return match;
        });

        if (matches.isNotEmpty) {
          final originalFilePath =
              matches.first.endsWith('>') ? matches.first : entry.key;

          final conflictingFilePath =
              entry.key == originalFilePath ? matches.first : entry.key;

          return _RouteConflict(
            originalFilePath,
            conflictingFilePath,
            originalFilePath,
          );
        }

        return null;
      })
      .whereType<_RouteConflict>()
      .toSet();

  final conflictingEndpoints = [...directConflicts, ...indirectConflicts];

  if (conflictingEndpoints.isNotEmpty) {
    onViolationStart?.call();
    for (final conflict in conflictingEndpoints) {
      final originalFilePath = path.normalize(
        path.join('routes', conflict.originalFilePath),
      );
      final conflictingFilePath = path.normalize(
        path.join('routes', conflict.conflictingFilePath),
      );
      onRouteConflict?.call(
        originalFilePath,
        conflictingFilePath,
        conflict.conflictingEndpoint,
      );
    }
    onViolationEnd?.call();
  }
}