Failure.fromGraphQLError constructor

Failure.fromGraphQLError(
  1. Map<String, dynamic> err, {
  2. String? operation,
  3. String? url,
  4. String? method,
})

Build from a GraphQL error map (Apollo/Ktor/etc). Accepts the standard shape: { message, locations, path, extensions: { code, http: { status }, requestId, traceId, validationErrors, retryAfter, ... } }

Implementation

factory Failure.fromGraphQLError(
  Map<String, dynamic> err, {
  String? operation,
  String? url,
  String? method,
}) {
  final ext =
      (err['extensions'] as Map?)?.cast<String, dynamic>() ?? const {};
  // Common Apollo-style picks
  final http = (ext['http'] as Map?)?.cast<String, dynamic>() ?? const {};
  final status =
      (http['status'] as num?)?.toInt() ?? (ext['status'] as num?)?.toInt();

  final code = ext['code']?.toString();
  final requestId =
      ext['requestId']?.toString() ?? http['requestId']?.toString();
  final traceId = ext['traceId']?.toString() ?? http['traceId']?.toString();
  final retryAfterIso = ext['retryAfter']?.toString();
  final retryAfter = retryAfterIso != null
      ? DateTime.tryParse(retryAfterIso)
      : null;

  // Validation can be various shapes; normalize to Map<String, List<String>>
  Map<String, List<String>>? validation;
  final v = ext['validation'] ?? ext['validationErrors'] ?? ext['errors'];
  if (v is Map) {
    validation = v.map((k, val) {
      final list = (val is List ? val : [val])
          .map((e) => e.toString())
          .toList();
      return MapEntry(k.toString(), list);
    }).cast<String, List<String>>();
  }

  // Category inference
  final category = _inferCategoryFromGraphQL(
    code: code,
    status: status,
    validation: validation,
  );

  return Failure(
    errorMessage: err['message']?.toString() ?? 'An error occurred.',
    i18nKey: ext['i18nKey']?.toString(),
    category: category,
    code: code,
    operation: operation,
    locations: (err['locations'] as List?)
        ?.cast<Map>()
        .map((e) => e.cast<String, dynamic>())
        .toList(),
    path: (err['path'] as List?)?.toList(),
    extensions: ext,
    status: status,
    requestId: requestId,
    traceId: traceId,
    service: ext['service']?.toString(),
    validation: validation,
    retryable: (ext['retryable'] as bool?) ?? _isRetryable(category, status),
    retryAfter: retryAfter,
    url: url,
    method: method,
    tokenExpired: ext['tokenExpired'] as bool?,
    canRefresh: ext['canRefresh'] as bool?,
    debugMessage: (ext['exception'] as Map?)?['message']?.toString(),
    stackTrace: (ext['exception'] as Map?)?['stacktrace']?.toString(),
  );
}