2016-12-09 00:24:07 +00:00
|
|
|
import 'dart:async';
|
2018-08-26 22:41:01 +00:00
|
|
|
import 'dart:convert';
|
2016-12-09 00:24:07 +00:00
|
|
|
import 'package:http/src/base_client.dart' as http;
|
|
|
|
import 'package:http/src/base_request.dart' as http;
|
|
|
|
import 'package:http/src/request.dart' as http;
|
|
|
|
import 'package:http/src/response.dart' as http;
|
|
|
|
import 'package:http/src/streamed_response.dart' as http;
|
2021-07-09 14:19:16 +00:00
|
|
|
import 'package:path/path.dart';
|
2021-07-15 08:11:54 +00:00
|
|
|
import 'package:logging/logging.dart';
|
2021-05-15 06:53:03 +00:00
|
|
|
import 'angel3_client.dart';
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2021-02-21 02:47:23 +00:00
|
|
|
const Map<String, String> _readHeaders = {'Accept': 'application/json'};
|
|
|
|
const Map<String, String> _writeHeaders = {
|
2016-12-13 16:34:22 +00:00
|
|
|
'Accept': 'application/json',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
};
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2021-07-09 14:19:16 +00:00
|
|
|
Map<String, String> _buildQuery(Map<String, dynamic>? params) {
|
|
|
|
return params?.map((k, v) => MapEntry(k, v.toString())) ?? {};
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2017-03-29 01:52:19 +00:00
|
|
|
bool _invalid(http.Response response) =>
|
2021-04-26 00:47:32 +00:00
|
|
|
response.statusCode < 200 || response.statusCode >= 300;
|
2017-03-29 01:52:19 +00:00
|
|
|
|
2018-11-04 01:34:21 +00:00
|
|
|
AngelHttpException failure(http.Response response,
|
2021-04-10 13:22:20 +00:00
|
|
|
{error, String? message, StackTrace? stack}) {
|
2016-12-09 00:24:07 +00:00
|
|
|
try {
|
2019-01-06 02:08:31 +00:00
|
|
|
var v = json.decode(response.body);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2018-11-04 01:34:21 +00:00
|
|
|
if (v is Map && (v['is_error'] == true) || v['isError'] == true) {
|
2021-02-21 02:47:23 +00:00
|
|
|
return AngelHttpException.fromMap(v as Map);
|
2016-12-09 00:24:07 +00:00
|
|
|
} else {
|
2022-02-21 01:17:27 +00:00
|
|
|
return AngelHttpException(
|
2018-11-04 01:34:21 +00:00
|
|
|
message: message ??
|
|
|
|
'Unhandled exception while connecting to Angel backend.',
|
2016-12-09 00:24:07 +00:00
|
|
|
statusCode: response.statusCode,
|
|
|
|
stackTrace: stack);
|
|
|
|
}
|
|
|
|
} catch (e, st) {
|
2022-02-21 01:17:27 +00:00
|
|
|
return AngelHttpException(
|
2018-11-04 01:34:21 +00:00
|
|
|
message: message ??
|
|
|
|
'Angel backend did not return JSON - an error likely occurred.',
|
2016-12-09 00:24:07 +00:00
|
|
|
statusCode: response.statusCode,
|
|
|
|
stackTrace: stack ?? st);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class BaseAngelClient extends Angel {
|
2021-07-15 08:11:54 +00:00
|
|
|
final _log = Logger('BaseAngelClient');
|
2017-06-03 17:43:01 +00:00
|
|
|
final StreamController<AngelAuthResult> _onAuthenticated =
|
2021-02-21 02:47:23 +00:00
|
|
|
StreamController<AngelAuthResult>();
|
2017-06-03 17:43:01 +00:00
|
|
|
final List<Service> _services = [];
|
2021-07-09 14:19:16 +00:00
|
|
|
final http.BaseClient client;
|
|
|
|
|
2021-07-10 04:32:42 +00:00
|
|
|
final Context _p = Context(style: Style.url);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2017-06-03 17:43:01 +00:00
|
|
|
@override
|
|
|
|
Stream<AngelAuthResult> get onAuthenticated => _onAuthenticated.stream;
|
|
|
|
|
2019-01-06 02:33:10 +00:00
|
|
|
BaseAngelClient(this.client, baseUrl) : super(baseUrl);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Future<AngelAuthResult> authenticate(
|
2022-02-21 01:17:27 +00:00
|
|
|
{String? type, credentials, String authEndpoint = '/auth'}) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
type ??= 'token';
|
|
|
|
|
|
|
|
var segments = baseUrl.pathSegments
|
2021-07-09 14:19:16 +00:00
|
|
|
.followedBy(_p.split(authEndpoint))
|
2019-01-06 02:08:31 +00:00
|
|
|
.followedBy([type]);
|
2021-03-05 07:51:48 +00:00
|
|
|
|
2021-07-09 14:19:16 +00:00
|
|
|
//var p1 = p.joinAll(segments).replaceAll('\\', '/');
|
2021-03-05 07:51:48 +00:00
|
|
|
|
2021-07-09 14:19:16 +00:00
|
|
|
var url = baseUrl.replace(path: _p.joinAll(segments));
|
2019-01-06 02:08:31 +00:00
|
|
|
http.Response response;
|
|
|
|
|
|
|
|
if (credentials != null) {
|
|
|
|
response = await post(url,
|
|
|
|
body: json.encode(credentials), headers: _writeHeaders);
|
2016-12-09 00:24:07 +00:00
|
|
|
} else {
|
2019-01-06 02:08:31 +00:00
|
|
|
response = await post(url, headers: _writeHeaders);
|
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
if (_invalid(response)) {
|
|
|
|
throw failure(response);
|
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
try {
|
2021-02-21 02:47:23 +00:00
|
|
|
//var v = json.decode(response.body);
|
2021-07-15 08:11:54 +00:00
|
|
|
_log.info(response.headers);
|
|
|
|
|
2021-02-21 02:47:23 +00:00
|
|
|
var v = jsonDecode(response.body);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2021-04-10 13:22:20 +00:00
|
|
|
if (v is! Map || !v.containsKey('data') || !v.containsKey('token')) {
|
2021-02-21 02:47:23 +00:00
|
|
|
throw AngelHttpException.notAuthenticated(
|
2019-01-06 02:08:31 +00:00
|
|
|
message: "Auth endpoint '$url' did not return a proper response.");
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2019-01-06 02:08:31 +00:00
|
|
|
|
2021-04-10 13:22:20 +00:00
|
|
|
var r = AngelAuthResult.fromMap(v);
|
2019-01-06 02:08:31 +00:00
|
|
|
_onAuthenticated.add(r);
|
|
|
|
return r;
|
|
|
|
} on AngelHttpException {
|
|
|
|
rethrow;
|
|
|
|
} catch (e, st) {
|
2021-07-15 08:11:54 +00:00
|
|
|
_log.severe('Authentication failed');
|
2019-01-06 02:08:31 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-21 02:47:23 +00:00
|
|
|
@override
|
2019-01-06 02:08:31 +00:00
|
|
|
Future<void> close() async {
|
2021-07-09 14:19:16 +00:00
|
|
|
client.close();
|
2019-04-20 15:21:15 +00:00
|
|
|
await _onAuthenticated.close();
|
|
|
|
await Future.wait(_services.map((s) => s.close())).then((_) {
|
2017-06-03 17:43:01 +00:00
|
|
|
_services.clear();
|
|
|
|
});
|
2016-12-10 14:50:05 +00:00
|
|
|
}
|
|
|
|
|
2021-02-21 02:47:23 +00:00
|
|
|
@override
|
2019-01-06 02:08:31 +00:00
|
|
|
Future<void> logout() async {
|
2017-03-29 01:52:19 +00:00
|
|
|
authToken = null;
|
|
|
|
}
|
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
@override
|
|
|
|
Future<http.StreamedResponse> send(http.BaseRequest request) async {
|
2021-02-21 02:47:23 +00:00
|
|
|
if (authToken?.isNotEmpty == true) {
|
2019-01-06 02:08:31 +00:00
|
|
|
request.headers['authorization'] ??= 'Bearer $authToken';
|
2021-02-21 02:47:23 +00:00
|
|
|
}
|
2021-07-09 14:19:16 +00:00
|
|
|
return client.send(request);
|
2019-01-06 02:08:31 +00:00
|
|
|
}
|
|
|
|
|
2017-01-25 23:25:31 +00:00
|
|
|
/// Sends a non-streaming [Request] and returns a non-streaming [Response].
|
|
|
|
Future<http.Response> sendUnstreamed(
|
2021-04-10 13:22:20 +00:00
|
|
|
String method, url, Map<String, String>? headers,
|
|
|
|
[body, Encoding? encoding]) async {
|
2018-08-26 22:41:01 +00:00
|
|
|
var request =
|
2021-02-21 02:47:23 +00:00
|
|
|
http.Request(method, url is Uri ? url : Uri.parse(url.toString()));
|
2017-01-25 23:25:31 +00:00
|
|
|
|
|
|
|
if (headers != null) request.headers.addAll(headers);
|
|
|
|
|
|
|
|
if (encoding != null) request.encoding = encoding;
|
|
|
|
if (body != null) {
|
|
|
|
if (body is String) {
|
|
|
|
request.body = body;
|
2019-01-06 02:08:31 +00:00
|
|
|
} else if (body is List<int>) {
|
2021-02-21 02:47:23 +00:00
|
|
|
request.bodyBytes = List<int>.from(body);
|
2019-04-20 15:23:06 +00:00
|
|
|
} else if (body is Map<String, dynamic>) {
|
|
|
|
request.bodyFields =
|
|
|
|
body.map((k, v) => MapEntry(k, v is String ? v : v.toString()));
|
2017-01-25 23:25:31 +00:00
|
|
|
} else {
|
2021-07-15 08:11:54 +00:00
|
|
|
_log.severe('Body is not a String, List<int>, or Map<String, String>');
|
2021-02-21 02:47:23 +00:00
|
|
|
throw ArgumentError.value(body, 'body',
|
2019-01-06 02:08:31 +00:00
|
|
|
'must be a String, List<int>, or Map<String, String>.');
|
2017-01-25 23:25:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
return http.Response.fromStream(await send(request));
|
2017-01-25 23:25:31 +00:00
|
|
|
}
|
|
|
|
|
2016-12-09 00:24:07 +00:00
|
|
|
@override
|
2018-10-02 15:42:26 +00:00
|
|
|
Service<Id, Data> service<Id, Data>(String path,
|
2021-04-10 13:22:20 +00:00
|
|
|
{Type? type, AngelDeserializer<Data>? deserializer}) {
|
2021-07-09 14:19:16 +00:00
|
|
|
var url = baseUrl.replace(path: _p.join(baseUrl.path, path));
|
2021-02-21 02:47:23 +00:00
|
|
|
var s = BaseAngelService<Id, Data>(client, this, url,
|
2016-12-13 16:35:35 +00:00
|
|
|
deserializer: deserializer);
|
2017-06-03 17:43:01 +00:00
|
|
|
_services.add(s);
|
2021-04-10 13:22:20 +00:00
|
|
|
return s as Service<Id, Data>;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2016-12-10 17:15:54 +00:00
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
Uri _join(url) {
|
|
|
|
var u = url is Uri ? url : Uri.parse(url.toString());
|
|
|
|
if (u.hasScheme || u.hasAuthority) return u;
|
2021-07-09 14:19:16 +00:00
|
|
|
return u.replace(path: _p.join(baseUrl.path, u.path));
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
|
|
|
|
2021-03-07 16:02:53 +00:00
|
|
|
//@override
|
|
|
|
//Future<http.Response> delete(url, {Map<String, String> headers}) async {
|
|
|
|
// return sendUnstreamed('DELETE', _join(url), headers);
|
|
|
|
//}
|
2016-12-10 17:15:54 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<http.Response> get(url, {Map<String, String>? headers}) async {
|
2017-01-25 23:25:31 +00:00
|
|
|
return sendUnstreamed('GET', _join(url), headers);
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<http.Response> head(url, {Map<String, String>? headers}) async {
|
2017-01-25 23:25:31 +00:00
|
|
|
return sendUnstreamed('HEAD', _join(url), headers);
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2019-01-06 02:08:31 +00:00
|
|
|
Future<http.Response> patch(url,
|
2021-04-10 13:22:20 +00:00
|
|
|
{body, Map<String, String>? headers, Encoding? encoding}) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
return sendUnstreamed('PATCH', _join(url), headers, body, encoding);
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2019-01-06 02:08:31 +00:00
|
|
|
Future<http.Response> post(url,
|
2021-04-10 13:22:20 +00:00
|
|
|
{body, Map<String, String>? headers, Encoding? encoding}) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
return sendUnstreamed('POST', _join(url), headers, body, encoding);
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2019-01-06 02:08:31 +00:00
|
|
|
Future<http.Response> put(url,
|
2021-04-10 13:22:20 +00:00
|
|
|
{body, Map<String, String>? headers, Encoding? encoding}) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
return sendUnstreamed('PUT', _join(url), headers, body, encoding);
|
2016-12-10 17:15:54 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2021-04-10 13:22:20 +00:00
|
|
|
class BaseAngelService<Id, Data> extends Service<Id, Data?> {
|
2016-12-09 00:24:07 +00:00
|
|
|
@override
|
2017-01-25 23:25:31 +00:00
|
|
|
final BaseAngelClient app;
|
2019-01-06 02:08:31 +00:00
|
|
|
final Uri baseUrl;
|
2021-07-09 14:19:16 +00:00
|
|
|
final http.BaseClient client;
|
2021-04-10 13:22:20 +00:00
|
|
|
final AngelDeserializer<Data>? deserializer;
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2021-07-10 04:32:42 +00:00
|
|
|
final Context _p = Context(style: Style.url);
|
2021-07-09 14:19:16 +00:00
|
|
|
|
2021-04-10 13:22:20 +00:00
|
|
|
final StreamController<List<Data?>> _onIndexed = StreamController();
|
|
|
|
final StreamController<Data?> _onRead = StreamController(),
|
2021-02-21 02:47:23 +00:00
|
|
|
_onCreated = StreamController(),
|
|
|
|
_onModified = StreamController(),
|
|
|
|
_onUpdated = StreamController(),
|
|
|
|
_onRemoved = StreamController();
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<List<Data?>> get onIndexed => _onIndexed.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<Data?> get onRead => _onRead.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<Data?> get onCreated => _onCreated.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<Data?> get onModified => _onModified.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<Data?> get onUpdated => _onUpdated.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Stream<Data?> get onRemoved => _onRemoved.stream;
|
2017-06-03 17:43:01 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Future close() async {
|
2019-04-20 15:21:15 +00:00
|
|
|
await _onIndexed.close();
|
|
|
|
await _onRead.close();
|
|
|
|
await _onCreated.close();
|
|
|
|
await _onModified.close();
|
|
|
|
await _onUpdated.close();
|
|
|
|
await _onRemoved.close();
|
2017-06-03 17:43:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
BaseAngelService(this.client, this.app, baseUrl, {this.deserializer})
|
2021-04-26 00:47:32 +00:00
|
|
|
: baseUrl = baseUrl is Uri ? baseUrl : Uri.parse(baseUrl.toString());
|
2019-01-06 02:08:31 +00:00
|
|
|
|
2021-04-10 13:22:20 +00:00
|
|
|
Data? deserialize(x) {
|
|
|
|
return deserializer != null ? deserializer!(x) : x as Data?;
|
2016-12-13 16:35:35 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
|
2021-02-21 02:47:23 +00:00
|
|
|
String makeBody(x) {
|
|
|
|
//return json.encode(x);
|
|
|
|
return jsonEncode(x);
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<http.StreamedResponse> send(http.BaseRequest request) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (app.authToken != null && app.authToken!.isNotEmpty) {
|
2016-12-09 00:24:07 +00:00
|
|
|
request.headers['Authorization'] = 'Bearer ${app.authToken}';
|
|
|
|
}
|
|
|
|
|
2021-07-09 14:19:16 +00:00
|
|
|
return client.send(request);
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-07-09 14:19:16 +00:00
|
|
|
Future<List<Data>> index([Map<String, dynamic>? params]) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(queryParameters: _buildQuery(params));
|
|
|
|
var response = await app.sendUnstreamed('GET', url, _readHeaders);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-02-21 02:47:23 +00:00
|
|
|
if (_onIndexed.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onIndexed.addError(failure(response));
|
2021-02-21 02:47:23 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-02-21 02:47:23 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-01-06 02:08:31 +00:00
|
|
|
var v = json.decode(response.body) as List;
|
2021-07-09 14:19:16 +00:00
|
|
|
//var r = v.map(deserialize).toList();
|
|
|
|
var r = <Data>[];
|
2022-02-21 01:17:27 +00:00
|
|
|
for (var element in v) {
|
2021-07-09 14:19:16 +00:00
|
|
|
var a = deserialize(element);
|
|
|
|
if (a != null) {
|
|
|
|
r.add(a);
|
|
|
|
}
|
2022-02-21 01:17:27 +00:00
|
|
|
}
|
2017-06-03 17:43:01 +00:00
|
|
|
_onIndexed.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-02-21 02:47:23 +00:00
|
|
|
if (_onIndexed.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onIndexed.addError(e, st);
|
2021-02-21 02:47:23 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-02-21 02:47:23 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
2021-07-09 14:19:16 +00:00
|
|
|
return [];
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<Data?> read(id, [Map<String, dynamic>? params]) async {
|
2021-07-09 14:19:16 +00:00
|
|
|
var pa = _p.join(baseUrl.path, id.toString());
|
|
|
|
print(pa);
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(
|
2021-07-09 14:19:16 +00:00
|
|
|
path: _p.join(baseUrl.path, id.toString()),
|
2019-01-06 02:08:31 +00:00
|
|
|
queryParameters: _buildQuery(params));
|
|
|
|
|
|
|
|
var response = await app.sendUnstreamed('GET', url, _readHeaders);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onRead.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onRead.addError(failure(response));
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:18:38 +00:00
|
|
|
var r = deserialize(json.decode(response.body));
|
2017-06-03 17:43:01 +00:00
|
|
|
_onRead.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onRead.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onRead.addError(e, st);
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
|
|
|
return null;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<Data?> create(data, [Map<String, dynamic>? params]) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(queryParameters: _buildQuery(params));
|
|
|
|
var response =
|
|
|
|
await app.sendUnstreamed('POST', url, _writeHeaders, makeBody(data));
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onCreated.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onCreated.addError(failure(response));
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:18:38 +00:00
|
|
|
var r = deserialize(json.decode(response.body));
|
2017-06-03 17:43:01 +00:00
|
|
|
_onCreated.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onCreated.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onCreated.addError(e, st);
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
|
|
|
return null;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<Data?> modify(id, data, [Map<String, dynamic>? params]) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(
|
2021-07-09 14:19:16 +00:00
|
|
|
path: _p.join(baseUrl.path, id.toString()),
|
2019-01-06 02:08:31 +00:00
|
|
|
queryParameters: _buildQuery(params));
|
|
|
|
|
|
|
|
var response =
|
|
|
|
await app.sendUnstreamed('PATCH', url, _writeHeaders, makeBody(data));
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onModified.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onModified.addError(failure(response));
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:18:38 +00:00
|
|
|
var r = deserialize(json.decode(response.body));
|
2017-06-03 17:43:01 +00:00
|
|
|
_onModified.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onModified.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onModified.addError(e, st);
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
|
|
|
return null;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<Data?> update(id, data, [Map<String, dynamic>? params]) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(
|
2021-07-09 14:19:16 +00:00
|
|
|
path: _p.join(baseUrl.path, id.toString()),
|
2019-01-06 02:08:31 +00:00
|
|
|
queryParameters: _buildQuery(params));
|
|
|
|
|
|
|
|
var response =
|
|
|
|
await app.sendUnstreamed('POST', url, _writeHeaders, makeBody(data));
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onUpdated.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onUpdated.addError(failure(response));
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:18:38 +00:00
|
|
|
var r = deserialize(json.decode(response.body));
|
2017-06-03 17:43:01 +00:00
|
|
|
_onUpdated.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onUpdated.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onUpdated.addError(e, st);
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
|
|
|
return null;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2021-04-10 13:22:20 +00:00
|
|
|
Future<Data?> remove(id, [Map<String, dynamic>? params]) async {
|
2019-01-06 02:08:31 +00:00
|
|
|
var url = baseUrl.replace(
|
2021-07-09 14:19:16 +00:00
|
|
|
path: _p.join(baseUrl.path, id.toString()),
|
2019-01-06 02:08:31 +00:00
|
|
|
queryParameters: _buildQuery(params));
|
|
|
|
|
|
|
|
var response = await app.sendUnstreamed('DELETE', url, _readHeaders);
|
2016-12-09 00:24:07 +00:00
|
|
|
|
|
|
|
try {
|
2017-03-29 01:52:19 +00:00
|
|
|
if (_invalid(response)) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onRemoved.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onRemoved.addError(failure(response));
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:18:38 +00:00
|
|
|
var r = deserialize(json.decode(response.body));
|
2017-06-03 17:43:01 +00:00
|
|
|
_onRemoved.add(r);
|
|
|
|
return r;
|
2016-12-09 00:24:07 +00:00
|
|
|
} catch (e, st) {
|
2021-04-10 13:22:20 +00:00
|
|
|
if (_onRemoved.hasListener) {
|
2017-12-21 20:08:45 +00:00
|
|
|
_onRemoved.addError(e, st);
|
2021-04-10 13:22:20 +00:00
|
|
|
} else {
|
2017-12-21 20:08:45 +00:00
|
|
|
throw failure(response, error: e, stack: st);
|
2021-04-10 13:22:20 +00:00
|
|
|
}
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
2018-11-04 01:34:21 +00:00
|
|
|
|
|
|
|
return null;
|
2016-12-09 00:24:07 +00:00
|
|
|
}
|
|
|
|
}
|