CommandResult.fromJson constructor

CommandResult.fromJson(
  1. Map<Object?, Object?> json
)

Implementation

factory CommandResult.fromJson(Map<Object?, Object?> json) {
  if (json['kind'] != 'zuke.command-result') {
    throw const FormatException(
      'Unsupported command result format; regenerate with the current Zuke CLI',
    );
  }
  String requiredString(String key) {
    final value = json[key];
    if (value is! String || value.isEmpty) {
      throw FormatException('Command result requires non-empty $key');
    }
    return value;
  }

  final exitCode = json['exitCode'];
  final eligible = json['eligible'];
  if (exitCode is! int || eligible is! bool) {
    throw const FormatException('Command result status fields are malformed');
  }
  final status = switch (requiredString('status')) {
    'passed' => CommandStatus.passed,
    'failed' => CommandStatus.failed,
    final value => throw FormatException('Unknown command status: $value'),
  };
  final consistent = switch (status) {
    CommandStatus.passed => exitCode == 0 && eligible,
    CommandStatus.failed => exitCode != 0 && !eligible,
  };
  if (!consistent) {
    throw const FormatException(
      'Command result status disagrees with exit code or eligibility',
    );
  }
  final diagnostics = json['diagnostics'];
  if (diagnostics is! List || diagnostics.any((item) => item is! Map)) {
    throw const FormatException('Command result diagnostics are malformed');
  }
  final details = <String, Object?>{};
  for (final entry in json.entries) {
    if (!const {
      'kind',
      'command',
      'stage',
      'exitCode',
      'status',
      'eligible',
      'diagnostics',
    }.contains(entry.key)) {
      details[entry.key.toString()] = entry.value;
    }
  }
  _validateNestedDetails(details);
  return CommandResult(
    command: requiredString('command'),
    stage: requiredString('stage'),
    exitCode: exitCode,
    status: status,
    eligible: eligible,
    diagnostics: diagnostics
        .cast<Map<Object?, Object?>>()
        .map(Diagnostic.fromJson)
        .toList(),
    details: details,
  );
}