Files
tdc114plus/app/lib/src/features/auth/data/auth_api_client.dart
T

105 lines
3.0 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../../core/network/api_error.dart';
import '../domain/auth_models.dart';
class AuthApiClient {
const AuthApiClient({
required this.httpClient,
required this.baseUri,
this.timeout = const Duration(seconds: 10),
});
final http.Client httpClient;
final Uri baseUri;
final Duration timeout;
Future<PhoneLoginResponse> phoneLogin(PhoneLoginRequest request) async {
final response = await httpClient
.post(
_resolve('/api/v1/tdc114plus/auth/phone-login'),
headers: const {
'accept': 'application/json',
'content-type': 'application/json',
},
body: jsonEncode(request.toJson()),
)
.timeout(timeout);
final decoded = _decodeObject(response.body);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw ApiException(
statusCode: response.statusCode,
apiError: ApiError.fromJson(decoded),
);
}
return PhoneLoginResponse.fromJson(decoded);
}
Future<PhoneLoginLinkInitResponse> requestPhoneLoginLink(
PhoneLoginLinkInitRequest request,
) async {
final response = await httpClient
.post(
_resolve('/api/v1/auth/link/init'),
headers: const {
'accept': 'application/json',
'content-type': 'application/json',
},
body: jsonEncode(request.toJson()),
)
.timeout(timeout);
final decoded = _decodeObject(response.body);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw ApiException(
statusCode: response.statusCode,
apiError: ApiError.fromJson(decoded),
);
}
return PhoneLoginLinkInitResponse.fromJson(decoded);
}
Future<PhoneLoginLinkPollResponse> pollPhoneLoginLink(
PhoneLoginLinkPollRequest request,
) async {
final response = await httpClient
.post(
_resolve('/api/v1/auth/link/poll'),
headers: const {
'accept': 'application/json',
'content-type': 'application/json',
},
body: jsonEncode(request.toJson()),
)
.timeout(timeout);
final decoded = _decodeObject(response.body);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw ApiException(
statusCode: response.statusCode,
apiError: ApiError.fromJson(decoded),
);
}
return PhoneLoginLinkPollResponse.fromJson(decoded);
}
Uri _resolve(String path) {
final normalizedBase = baseUri.path.endsWith('/')
? baseUri
: baseUri.replace(path: '${baseUri.path}/');
return normalizedBase.resolve(path.replaceFirst(RegExp(r'^/'), ''));
}
Map<String, dynamic> _decodeObject(String body) {
final decoded = jsonDecode(body);
if (decoded is Map<String, dynamic>) {
return decoded;
}
throw const FormatException('Expected JSON object response');
}
}