import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:sunny_mochi/core/error/failures.dart'; import 'package:sunny_mochi/core/network/response_code.dart'; part 'api_response.freezed.dart'; part 'api_response.g.dart'; @Freezed(genericArgumentFactories: true) abstract class ApiResponse with _$ApiResponse { const factory ApiResponse({ @JsonKey(name: 'code') required String retCode, @Default('') @JsonKey(name: 'msg') String retMsg, @JsonKey(name: 'data') T? retData, }) = _ApiResponse; factory ApiResponse.fromJson( Map json, T Function(Object?) fromJsonT, ) => _$ApiResponseFromJson(json, fromJsonT); } extension ApiResponseX on ApiResponse { bool get isSuccess => ResponseCode.isSuccess(retCode); bool get isTokenExpired => ResponseCode.isUnauthorized(retCode); T? unwrap() { if (!isSuccess) throw ServerFailure(message: retMsg, code: retCode); return retData; } void unwrapVoid() { if (!isSuccess) throw ServerFailure(message: retMsg, code: retCode); } T unwrapRequired([String errorMsg = '响应数据为空']) { final data = unwrap(); if (data == null) throw ServerFailure(message: errorMsg); return data; } } /// Datasource 层 envelope 解析入口。 /// /// 用法:`parseEnvelope(resp.data, (j) => MyModel.fromJson(j))?.unwrap()` ApiResponse parseEnvelope( Map? body, T Function(Object?) fromJsonT, { String emptyMsg = '响应为空', }) { if (body == null) throw ServerFailure(message: emptyMsg); return ApiResponse.fromJson(body, fromJsonT); }