Common code :)
This commit is contained in:
parent
c220a48830
commit
90af9f9bb6
8 changed files with 374 additions and 294 deletions
1
.travis.yml
Normal file
1
.travis.yml
Normal file
|
@ -0,0 +1 @@
|
|||
language: dart
|
|
@ -1,4 +1,8 @@
|
|||
# angel_client
|
||||
|
||||
[![pub 1.0.0-dev+16](https://img.shields.io/badge/pub-1.0.0--dev+16-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||
![build status](https://travis-ci.org/angel-dart/client.svg)
|
||||
|
||||
Client library for the Angel framework.
|
||||
|
||||
# Isomorphic
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
library angel_client;
|
||||
|
||||
import 'dart:async';
|
||||
import 'auth_types.dart' as auth_types;
|
||||
import 'dart:convert';
|
||||
export 'package:angel_framework/src/http/angel_http_exception.dart';
|
||||
|
||||
/// A function that configures an [Angel] client in some way.
|
||||
typedef Future AngelConfigurer(Angel app);
|
||||
|
||||
/// Represents an Angel server that we are querying.
|
||||
abstract class Angel {
|
||||
String get authToken;
|
||||
String basePath;
|
||||
|
||||
Angel(String this.basePath);
|
||||
|
@ -28,11 +30,33 @@ abstract class Angel {
|
|||
}
|
||||
|
||||
/// Represents the result of authentication with an Angel server.
|
||||
abstract class AngelAuthResult {
|
||||
Map<String, dynamic> get data;
|
||||
String get token;
|
||||
class AngelAuthResult {
|
||||
String _token;
|
||||
final Map<String, dynamic> data = {};
|
||||
String get token => _token;
|
||||
|
||||
Map<String, dynamic> toJson();
|
||||
AngelAuthResult({String token, Map<String, dynamic> data: const {}}) {
|
||||
_token = token;
|
||||
this.data.addAll(data ?? {});
|
||||
}
|
||||
|
||||
factory AngelAuthResult.fromMap(Map data) {
|
||||
final result = new AngelAuthResult();
|
||||
|
||||
if (data is Map && data.containsKey('token') && data['token'] is String)
|
||||
result._token = data['token'];
|
||||
|
||||
if (data is Map) result.data.addAll(data['data'] ?? {});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
factory AngelAuthResult.fromJson(String json) =>
|
||||
new AngelAuthResult.fromMap(JSON.decode(json));
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'token': token, 'data': data};
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries a service on an Angel server, with the same API.
|
||||
|
|
278
lib/base_angel_client.dart
Normal file
278
lib/base_angel_client.dart
Normal file
|
@ -0,0 +1,278 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:angel_framework/src/http/angel_http_exception.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
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;
|
||||
import 'package:merge_map/merge_map.dart';
|
||||
import 'angel_client.dart';
|
||||
import 'auth_types.dart' as auth_types;
|
||||
|
||||
const Map<String, String> _readHeaders = const {'Accept': 'application/json'};
|
||||
final Map<String, String> _writeHeaders = mergeMap([
|
||||
_readHeaders,
|
||||
const {'Content-Type': 'application/json'}
|
||||
]);
|
||||
|
||||
_buildQuery(Map params) {
|
||||
if (params == null || params.isEmpty) return "";
|
||||
|
||||
List<String> query = [];
|
||||
|
||||
params.forEach((k, v) {
|
||||
query.add('$k=$v');
|
||||
});
|
||||
|
||||
return '?' + query.join('&');
|
||||
}
|
||||
|
||||
AngelHttpException failure(http.Response response, {error, StackTrace stack}) {
|
||||
try {
|
||||
final json = JSON.decode(response.body);
|
||||
|
||||
if (json is Map && json['isError'] == true) {
|
||||
return new AngelHttpException.fromMap(json);
|
||||
} else {
|
||||
return new AngelHttpException(error,
|
||||
message: 'Unhandled exception while connecting to Angel backend.',
|
||||
statusCode: response.statusCode,
|
||||
stackTrace: stack);
|
||||
}
|
||||
} catch (e, st) {
|
||||
return new AngelHttpException(error ?? e,
|
||||
message: 'Unhandled exception while connecting to Angel backend.',
|
||||
statusCode: response.statusCode,
|
||||
stackTrace: stack ?? st);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseAngelClient extends Angel {
|
||||
@override
|
||||
String authToken;
|
||||
|
||||
final http.BaseClient client;
|
||||
|
||||
BaseAngelClient(this.client, String basePath) : super(basePath);
|
||||
|
||||
@override
|
||||
Future<AngelAuthResult> authenticate(
|
||||
{String type: auth_types.LOCAL,
|
||||
credentials,
|
||||
String authEndpoint: '/auth',
|
||||
String reviveEndpoint: '/auth/token'}) async {
|
||||
if (type == null) {
|
||||
final url = '$basePath$reviveEndpoint';
|
||||
final response = await client.post(url,
|
||||
headers: mergeMap([
|
||||
_writeHeaders,
|
||||
{'Authorization': 'Bearer ${credentials['token']}'}
|
||||
]));
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
final json = JSON.decode(response.body);
|
||||
|
||||
if (json is! Map ||
|
||||
!json.containsKey('data') ||
|
||||
!json.containsKey('token')) {
|
||||
throw new AngelHttpException.NotAuthenticated(
|
||||
message:
|
||||
"Auth endpoint '$url' did not return a proper response.");
|
||||
}
|
||||
|
||||
return new AngelAuthResult.fromMap(json);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
} else {
|
||||
final url = '$basePath$authEndpoint/$type';
|
||||
http.Response response;
|
||||
|
||||
if (credentials != null) {
|
||||
response = await client.post(url,
|
||||
body: JSON.encode(credentials), headers: _writeHeaders);
|
||||
} else {
|
||||
response = await client.post(url, headers: _writeHeaders);
|
||||
}
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
final json = JSON.decode(response.body);
|
||||
|
||||
if (json is! Map ||
|
||||
!json.containsKey('data') ||
|
||||
!json.containsKey('token')) {
|
||||
throw new AngelHttpException.NotAuthenticated(
|
||||
message:
|
||||
"Auth endpoint '$url' did not return a proper response.");
|
||||
}
|
||||
|
||||
return new AngelAuthResult.fromMap(json);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Service service(String path, {Type type}) {
|
||||
String uri = path.replaceAll(new RegExp(r"(^/)|(/+$)"), "");
|
||||
return new BaseAngelService(client, this, '$basePath/$uri');
|
||||
}
|
||||
}
|
||||
|
||||
class BaseAngelService extends Service {
|
||||
@override
|
||||
final Angel app;
|
||||
final String basePath;
|
||||
final http.BaseClient client;
|
||||
|
||||
BaseAngelService(this.client, this.app, this.basePath);
|
||||
|
||||
makeBody(x) {
|
||||
return JSON.encode(x);
|
||||
}
|
||||
|
||||
/// Sends a non-streaming [Request] and returns a non-streaming [Response].
|
||||
Future<http.Response> sendUnstreamed(
|
||||
String method, url, Map<String, String> headers,
|
||||
[body, Encoding encoding]) async {
|
||||
if (url is String) url = Uri.parse(url);
|
||||
var request = new http.Request(method, url);
|
||||
|
||||
if (headers != null) request.headers.addAll(headers);
|
||||
if (encoding != null) request.encoding = encoding;
|
||||
if (body != null) {
|
||||
if (body is String) {
|
||||
request.body = body;
|
||||
} else if (body is List) {
|
||||
request.bodyBytes = DelegatingList.typed(body);
|
||||
} else if (body is Map) {
|
||||
request.bodyFields = DelegatingMap.typed(body);
|
||||
} else {
|
||||
throw new ArgumentError('Invalid request body "$body".');
|
||||
}
|
||||
}
|
||||
|
||||
return http.Response.fromStream(await client.send(request));
|
||||
}
|
||||
|
||||
Future<http.StreamedResponse> send(http.BaseRequest request) {
|
||||
if (app.authToken != null && app.authToken.isNotEmpty) {
|
||||
request.headers['Authorization'] = 'Bearer ${app.authToken}';
|
||||
}
|
||||
|
||||
return client.send(request);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List> index([Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'GET', '$basePath/${_buildQuery(params)}', _readHeaders);
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
final json = JSON.decode(response.body);
|
||||
|
||||
if (json is! List) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return json;
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future read(id, [Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'GET', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return JSON.decode(response.body);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future create(data, [Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'POST', '$basePath/${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return JSON.decode(response.body);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future modify(id, data, [Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'PATCH', '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return JSON.decode(response.body);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future update(id, data, [Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'POST', '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return JSON.decode(response.body);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future remove(id, [Map params]) async {
|
||||
final response = await sendUnstreamed(
|
||||
'DELETE', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
||||
|
||||
try {
|
||||
if (response.statusCode != 200) {
|
||||
throw failure(response);
|
||||
}
|
||||
|
||||
return JSON.decode(response.body);
|
||||
} catch (e, st) {
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
}
|
234
lib/browser.dart
234
lib/browser.dart
|
@ -1,54 +1,22 @@
|
|||
/// Browser library for the Angel framework.
|
||||
library angel_client.browser;
|
||||
|
||||
import 'dart:async' show Completer, Future;
|
||||
import 'dart:async' show Future;
|
||||
import 'dart:convert' show JSON;
|
||||
import 'dart:html' show HttpRequest, window;
|
||||
import 'dart:html' show window;
|
||||
import 'package:http/browser_client.dart' as http;
|
||||
import 'angel_client.dart';
|
||||
import 'auth_types.dart' as auth_types;
|
||||
import 'base_angel_client.dart';
|
||||
export 'angel_client.dart';
|
||||
|
||||
_buildQuery(Map params) {
|
||||
if (params == null || params == {}) return "";
|
||||
|
||||
String result = "";
|
||||
return result;
|
||||
}
|
||||
|
||||
_send(HttpRequest request, [data]) {
|
||||
final completer = new Completer<HttpRequest>();
|
||||
|
||||
request
|
||||
..onLoadEnd.listen((_) {
|
||||
completer.complete(request.response);
|
||||
})
|
||||
..onError.listen((_) {
|
||||
try {
|
||||
throw new Exception(
|
||||
'Request failed with status code ${request.status}.');
|
||||
} catch (e, st) {
|
||||
completer.completeError(e, st);
|
||||
}
|
||||
});
|
||||
|
||||
if (data == null)
|
||||
request.send();
|
||||
else if (data is String)
|
||||
request.send(data);
|
||||
else
|
||||
request.send(JSON.encode(data));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
/// Queries an Angel server via REST.
|
||||
class Rest extends Angel {
|
||||
String _authToken;
|
||||
|
||||
Rest(String basePath) : super(basePath);
|
||||
class Rest extends BaseAngelClient {
|
||||
Rest(String basePath) : super(new http.BrowserClient(), basePath);
|
||||
|
||||
@override
|
||||
Future authenticate(
|
||||
{String type,
|
||||
Future<AngelAuthResult> authenticate(
|
||||
{String type: auth_types.LOCAL,
|
||||
credentials,
|
||||
String authEndpoint: '/auth',
|
||||
String reviveEndpoint: '/auth/token'}) async {
|
||||
|
@ -58,177 +26,23 @@ class Rest extends Angel {
|
|||
'Cannot revive token from localStorage - there is none.');
|
||||
}
|
||||
|
||||
final result = new _AngelAuthResultImpl(
|
||||
token: JSON.decode(window.localStorage['token']),
|
||||
data: JSON.decode(window.localStorage['user']));
|
||||
final completer = new Completer();
|
||||
final request = new HttpRequest()..responseType = 'json';
|
||||
request.open('POST', '$basePath$reviveEndpoint');
|
||||
request.setRequestHeader('Accept', 'application/json');
|
||||
request.setRequestHeader('Content-Type', 'application/json');
|
||||
request.setRequestHeader('Authorization', 'Bearer ${result.token}');
|
||||
|
||||
request
|
||||
..onLoadEnd.listen((_) {
|
||||
final result = new _AngelAuthResultImpl.fromMap(request.response);
|
||||
_authToken = result.token;
|
||||
window.localStorage['token'] = JSON.encode(result.token);
|
||||
window.localStorage['user'] = JSON.encode(result.data);
|
||||
completer.complete(result);
|
||||
})
|
||||
..onError.listen((_) {
|
||||
try {
|
||||
throw new Exception(
|
||||
'Request failed with status code ${request.status}.');
|
||||
} catch (e, st) {
|
||||
completer.completeError(e, st);
|
||||
}
|
||||
});
|
||||
|
||||
request.send(JSON.encode(result));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
final url = '$basePath$authEndpoint/$type';
|
||||
|
||||
if (type == auth_types.LOCAL) {
|
||||
final completer = new Completer();
|
||||
final request = new HttpRequest();
|
||||
request.open('POST', url);
|
||||
request.responseType = 'json';
|
||||
request.setRequestHeader("Accept", "application/json");
|
||||
request.setRequestHeader("Content-Type", "application/json");
|
||||
|
||||
request
|
||||
..onLoadEnd.listen((_) {
|
||||
final result = new _AngelAuthResultImpl.fromMap(request.response);
|
||||
_authToken = result.token;
|
||||
window.localStorage['token'] = JSON.encode(result.token);
|
||||
window.localStorage['user'] = JSON.encode(result.data);
|
||||
completer.complete(result);
|
||||
})
|
||||
..onError.listen((_) {
|
||||
try {
|
||||
throw new Exception(
|
||||
'Request failed with status code ${request.status}.');
|
||||
} catch (e, st) {
|
||||
completer.completeError(e, st);
|
||||
}
|
||||
});
|
||||
|
||||
if (credentials == null)
|
||||
request.send();
|
||||
else
|
||||
request.send(JSON.encode(credentials));
|
||||
|
||||
return completer.future;
|
||||
try {
|
||||
final result = await super.authenticate(
|
||||
credentials: {'token': JSON.decode(window.localStorage['token'])},
|
||||
reviveEndpoint: reviveEndpoint);
|
||||
window.localStorage['token'] = JSON.encode(authToken = result.token);
|
||||
window.localStorage['user'] = JSON.encode(result.data);
|
||||
return result;
|
||||
} catch (e, st) {
|
||||
throw new AngelHttpException(e,
|
||||
message: 'Failed to revive auth token.', stackTrace: st);
|
||||
}
|
||||
} else {
|
||||
throw new Exception('angel_client cannot authenticate as "$type" yet.');
|
||||
final result = await super.authenticate(
|
||||
type: type, credentials: credentials, authEndpoint: authEndpoint);
|
||||
window.localStorage['token'] = JSON.encode(authToken = result.token);
|
||||
window.localStorage['user'] = JSON.encode(result.data);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
RestService service(String path, {Type type}) {
|
||||
String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), "");
|
||||
return new _RestServiceImpl(this, "$basePath/$uri");
|
||||
}
|
||||
}
|
||||
|
||||
abstract class RestService extends Service {
|
||||
RestService._(String basePath);
|
||||
}
|
||||
|
||||
class _AngelAuthResultImpl implements AngelAuthResult {
|
||||
String _token;
|
||||
final Map<String, dynamic> data = {};
|
||||
String get token => _token;
|
||||
|
||||
_AngelAuthResultImpl({token, Map<String, dynamic> data: const {}}) {
|
||||
if (token is String) _token = token;
|
||||
|
||||
this.data.addAll(data ?? {});
|
||||
}
|
||||
|
||||
factory _AngelAuthResultImpl.fromMap(Map data) {
|
||||
final result = new _AngelAuthResultImpl();
|
||||
|
||||
if (data is Map && data.containsKey('token') && data['token'] is String)
|
||||
result._token = data['token'];
|
||||
|
||||
if (data is Map) result.data.addAll(data['data'] ?? {});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'token': token, 'data': data};
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries an Angel service via REST.
|
||||
class _RestServiceImpl extends RestService {
|
||||
final Rest app;
|
||||
String _basePath;
|
||||
String get basePath => _basePath;
|
||||
|
||||
_RestServiceImpl(this.app, String basePath) : super._(basePath) {
|
||||
_basePath = basePath;
|
||||
}
|
||||
|
||||
_makeBody(data) {
|
||||
return JSON.encode(data);
|
||||
}
|
||||
|
||||
Future<HttpRequest> buildRequest(String url,
|
||||
{String method: "POST", bool write: true}) async {
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.open(method, url);
|
||||
request.responseType = "json";
|
||||
request.setRequestHeader("Accept", "application/json");
|
||||
if (write) request.setRequestHeader("Content-Type", "application/json");
|
||||
if (app._authToken != null)
|
||||
request.setRequestHeader("Authorization", "Bearer ${app._authToken}");
|
||||
return request;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List> index([Map params]) async {
|
||||
final request = await buildRequest('$basePath/${_buildQuery(params)}',
|
||||
method: 'GET', write: false);
|
||||
return await _send(request);
|
||||
}
|
||||
|
||||
@override
|
||||
Future read(id, [Map params]) async {
|
||||
final request = await buildRequest('$basePath/$id${_buildQuery(params)}',
|
||||
method: 'GET', write: false);
|
||||
return await _send(request);
|
||||
}
|
||||
|
||||
@override
|
||||
Future create(data, [Map params]) async {
|
||||
final request = await buildRequest("$basePath/${_buildQuery(params)}");
|
||||
return await _send(request, _makeBody(data));
|
||||
}
|
||||
|
||||
@override
|
||||
Future modify(id, data, [Map params]) async {
|
||||
final request = await buildRequest("$basePath/$id${_buildQuery(params)}",
|
||||
method: "PATCH");
|
||||
return await _send(request, _makeBody(data));
|
||||
}
|
||||
|
||||
@override
|
||||
Future update(id, data, [Map params]) async {
|
||||
final request = await buildRequest("$basePath/$id${_buildQuery(params)}");
|
||||
return await _send(request, _makeBody(data));
|
||||
}
|
||||
|
||||
@override
|
||||
Future remove(id, [Map params]) async {
|
||||
final request = await buildRequest("$basePath/$id${_buildQuery(params)}",
|
||||
method: "DELETE");
|
||||
return await _send(request);
|
||||
}
|
||||
}
|
||||
|
|
111
lib/io.dart
111
lib/io.dart
|
@ -2,109 +2,68 @@
|
|||
library angel_client.cli;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show JSON;
|
||||
import 'package:http/http.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_god/json_god.dart' as god;
|
||||
import 'angel_client.dart';
|
||||
import 'base_angel_client.dart';
|
||||
export 'angel_client.dart';
|
||||
|
||||
_buildQuery(Map params) {
|
||||
if (params == null || params == {})
|
||||
return "";
|
||||
|
||||
String result = "";
|
||||
return result;
|
||||
}
|
||||
|
||||
const Map _readHeaders = const {
|
||||
"Accept": "application/json"
|
||||
};
|
||||
|
||||
const Map _writeHeaders = const {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
|
||||
/// Queries an Angel server via REST.
|
||||
class Rest extends Angel {
|
||||
BaseClient client;
|
||||
|
||||
Rest(String path, BaseClient this.client) :super(path);
|
||||
class Rest extends BaseAngelClient {
|
||||
Rest(String path) : super(new http.Client(), path);
|
||||
|
||||
@override
|
||||
RestService service(String path, {Type type}) {
|
||||
String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), "");
|
||||
return new RestService._base("$basePath/$uri", client, type)
|
||||
..app = this;
|
||||
Service service(String path, {Type type}) {
|
||||
String uri = path.replaceAll(new RegExp(r"(^/)|(/+$)"), "");
|
||||
return new RestService(client, this, "$basePath/$uri", type);
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries an Angel service via REST.
|
||||
class RestService extends Service {
|
||||
String basePath;
|
||||
BaseClient client;
|
||||
Type outputType;
|
||||
class RestService extends BaseAngelService {
|
||||
final Type type;
|
||||
|
||||
RestService._base(Pattern path, BaseClient this.client,
|
||||
Type this.outputType) {
|
||||
this.basePath = (path is RegExp) ? path.pattern : path;
|
||||
RestService(http.BaseClient client, Angel app, String url, this.type)
|
||||
: super(client, app, url);
|
||||
|
||||
deserialize(x) {
|
||||
if (type != null) {
|
||||
return god.deserializeDatum(x, outputType: type);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
_makeBody(data) {
|
||||
if (outputType == null)
|
||||
return JSON.encode(data);
|
||||
else return god.serialize(data);
|
||||
@override
|
||||
makeBody(x) {
|
||||
if (type != null) {
|
||||
return super.makeBody(god.serializeObject(x));
|
||||
}
|
||||
|
||||
return super.makeBody(x);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List> index([Map params]) async {
|
||||
var response = await client.get(
|
||||
"$basePath/${_buildQuery(params)}", headers: _readHeaders);
|
||||
|
||||
if (outputType == null)
|
||||
return god.deserialize(response.body);
|
||||
|
||||
else {
|
||||
return JSON.decode(response.body).map((x) =>
|
||||
god.deserializeDatum(x, outputType: outputType)).toList();
|
||||
}
|
||||
final items = await super.index(params);
|
||||
return items.map(deserialize).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future read(id, [Map params]) async {
|
||||
var response = await client.get(
|
||||
"$basePath/$id${_buildQuery(params)}", headers: _readHeaders);
|
||||
return god.deserialize(response.body, outputType: outputType);
|
||||
}
|
||||
Future read(id, [Map params]) => super.read(id, params).then(deserialize);
|
||||
|
||||
@override
|
||||
Future create(data, [Map params]) async {
|
||||
var response = await client.post(
|
||||
"$basePath/${_buildQuery(params)}", body: _makeBody(data),
|
||||
headers: _writeHeaders);
|
||||
return god.deserialize(response.body, outputType: outputType);
|
||||
}
|
||||
Future create(data, [Map params]) =>
|
||||
super.create(data, params).then(deserialize);
|
||||
|
||||
@override
|
||||
Future modify(id, data, [Map params]) async {
|
||||
var response = await client.patch(
|
||||
"$basePath/$id${_buildQuery(params)}", body: _makeBody(data),
|
||||
headers: _writeHeaders);
|
||||
return god.deserialize(response.body, outputType: outputType);
|
||||
}
|
||||
Future modify(id, data, [Map params]) =>
|
||||
super.modify(id, data, params).then(deserialize);
|
||||
|
||||
@override
|
||||
Future update(id, data, [Map params]) async {
|
||||
var response = await client.patch(
|
||||
"$basePath/$id${_buildQuery(params)}", body: _makeBody(data),
|
||||
headers: _writeHeaders);
|
||||
return god.deserialize(response.body, outputType: outputType);
|
||||
}
|
||||
Future update(id, data, [Map params]) =>
|
||||
super.update(id, data, params).then(deserialize);
|
||||
|
||||
@override
|
||||
Future remove(id, [Map params]) async {
|
||||
var response = await client.delete(
|
||||
"$basePath/$id${_buildQuery(params)}", headers: _readHeaders);
|
||||
return god.deserialize(response.body, outputType: outputType);
|
||||
}
|
||||
Future remove(id, [Map params]) => super.remove(id, params).then(deserialize);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
name: angel_client
|
||||
version: 1.0.0-dev+15
|
||||
version: 1.0.0-dev+16
|
||||
description: Client library for the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_client
|
||||
dependencies:
|
||||
angel_framework: ">=1.0.0-dev <2.0.0"
|
||||
http: ">= 0.11.3 < 0.12.0"
|
||||
json_god: ">=2.0.0-beta <3.0.0"
|
||||
merge_map: ">=1.0.0 <2.0.0"
|
||||
dev_dependencies:
|
||||
angel_framework: ">=1.0.0-dev <2.0.0"
|
||||
test: ">= 0.12.13 < 0.13.0"
|
||||
|
|
|
@ -22,7 +22,7 @@ main() {
|
|||
serverApp.use("/postcards", new server.MemoryService<Postcard>());
|
||||
serverPostcards = serverApp.service("postcards");
|
||||
|
||||
clientApp = new client.Rest(url, new http.Client());
|
||||
clientApp = new client.Rest(url);
|
||||
clientPostcards = clientApp.service("postcards");
|
||||
clientTypedPostcards = clientApp.service("postcards", type: Postcard);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue