mergeCommands static method

List<NyCommand> mergeCommands({
  1. required List<NyCommand> projectCommands,
  2. required List<NyCommand> packageCommands,
  3. Iterable<String> reservedCommands = const [],
  4. void onWarning(
    1. String message
    )?,
})

Merges project and package commands. Precedence: reservedCommands (built-ins), then project, then packages; a shadowed command is dropped with an onWarning.

Implementation

static List<NyCommand> mergeCommands({
  required List<NyCommand> projectCommands,
  required List<NyCommand> packageCommands,
  Iterable<String> reservedCommands = const [],
  void Function(String message)? onWarning,
}) {
  final void Function(String message) warn =
      onWarning ?? MetroConsole.writeInYellow;
  final Set<String> reserved = reservedCommands.toSet();
  final Map<String, NyCommand> taken = {};
  final List<NyCommand> merged = [];

  for (final NyCommand command in projectCommands) {
    final String key = command.fullName;
    if (reserved.contains(key)) {
      warn(
        '[Metro] Skipping "$key" from $commandsFolder/commands.json - it is a built-in Metro command',
      );
      continue;
    }
    if (taken.containsKey(key)) continue;
    taken[key] = command;
    merged.add(command);
  }

  for (final NyCommand command in packageCommands) {
    final String key = command.fullName;
    if (reserved.contains(key)) {
      warn(
        '[Metro] Skipping "$key" from package "${command.package}" - it is a built-in Metro command',
      );
      continue;
    }
    final NyCommand? existing = taken[key];
    if (existing != null) {
      final String owner = existing.package == null
          ? 'your project'
          : 'package "${existing.package}"';
      warn(
        '[Metro] Skipping "$key" from package "${command.package}" - it is already defined by $owner',
      );
      continue;
    }
    taken[key] = command;
    merged.add(command);
  }

  return merged;
}