tuuli_app/lib/api/api_client.dart

154 lines
4.1 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:tuuli_app/api/model/access_token_model.dart';
import 'package:http/browser_client.dart';
import 'package:http/http.dart';
import 'package:tuuli_app/api/model/table_field_model.dart';
import 'package:tuuli_app/api/model/tables_list_model.dart';
class ErrorOrData<T> {
final T? data;
final Exception? error;
ErrorOrData(this.data, this.error);
void unfold(
void Function(T data) onData, void Function(Exception error) onError) {
if (data != null) {
onData(data as T);
} else {
onError(error!);
}
}
}
typedef FutureErrorOrData<T> = Future<ErrorOrData<T>>;
class ApiClient {
final BrowserClient _client = BrowserClient();
var _accessToken = '';
final Uri baseUrl;
ApiClient(this.baseUrl);
ApiClient.fromString(String baseUrl) : this(Uri.parse(baseUrl));
void setAccessToken(String accessToken) {
_accessToken = accessToken;
}
FutureErrorOrData<AccessTokenModel> login(
String username,
String password,
) async {
AccessTokenModel? data;
Exception? error;
final response = await post('/api/getAccessToken', body: {
'username': username,
'password': password,
}, headers: {
'Content-Type': 'application/json',
});
if (response.statusCode == 200) {
final body = json.decode(await response.stream.bytesToString());
if (body['error'] != null) {
error = Exception(body['error']);
} else if (body['access_token'] == null) {
error = Exception('No access token');
} else {
data = AccessTokenModel(accessToken: body['access_token']);
}
} else if (response.statusCode == 422) {
error = Exception('Invalid request parameters');
} else {
error = Exception('HTTP ${response.statusCode}');
}
return ErrorOrData(data, error);
}
FutureErrorOrData<TablesListModel> tablesList() async {
TablesListModel? data;
Exception? error;
final response = await get('/api/listTables');
if (response.statusCode == 200) {
final body = json.decode(await response.stream.bytesToString());
if (body['error'] != null) {
error = Exception(body['error']);
} else if (body['tables'] == null) {
error = Exception('Server error');
} else {
data = TablesListModel.fromJson(body);
}
} else if (response.statusCode == 422) {
error = Exception('Invalid request parameters');
} else {
error = Exception('HTTP ${response.statusCode}');
}
return ErrorOrData(data, error);
}
FutureErrorOrData<void> createTable(
String tableName, List<TableField> columns) async {
Exception? error;
final response =
await post('/api/createTable/${Uri.encodeComponent(tableName)}', body: {
'columns':
columns.map((e) => e.toColumnDefinition()).toList(growable: false),
}, headers: {
'Content-Type': 'application/json',
});
if (response.statusCode == 200) {
final body = json.decode(await response.stream.bytesToString());
if (body['error'] != null) {
error = Exception(body['error']);
}
} else if (response.statusCode == 422) {
error = Exception('Invalid request parameters');
} else {
error = Exception('HTTP ${response.statusCode}');
}
return ErrorOrData(null, error);
}
Future<StreamedResponse> get(
String path, {
Map<String, String>? headers,
}) {
return _request(path, 'GET', headers: headers);
}
Future<StreamedResponse> post(
String path, {
Map<String, String>? headers,
dynamic body,
}) {
return _request(path, 'POST', headers: headers, body: body);
}
Future<StreamedResponse> _request(
String path,
String method, {
Map<String, String>? headers,
dynamic body,
}) async {
final uri = baseUrl.resolve(path);
final request = Request(method, uri);
if (headers != null) {
request.headers.addAll(headers);
}
if (_accessToken.isNotEmpty) {
request.headers["Access-Token"] = _accessToken;
}
if (body != null) {
request.body = json.encode(body);
}
return _client.send(request);
}
}