platform/lib/browser.dart

192 lines
5.4 KiB
Dart
Raw Normal View History

2016-06-25 18:37:49 +00:00
/// Browser library for the Angel framework.
library angel_client.browser;
2016-11-28 03:28:41 +00:00
import 'dart:async' show Completer, Future;
2016-06-25 18:37:49 +00:00
import 'dart:convert' show JSON;
2016-11-28 03:34:04 +00:00
import 'dart:html' show HttpRequest, window;
2016-09-03 12:02:32 +00:00
import 'angel_client.dart';
2016-11-28 03:28:41 +00:00
import 'auth_types.dart' as auth_types;
2016-09-03 12:02:32 +00:00
export 'angel_client.dart';
2016-06-25 18:37:49 +00:00
_buildQuery(Map params) {
2016-11-28 03:28:41 +00:00
if (params == null || params == {}) return "";
2016-06-25 18:37:49 +00:00
String result = "";
return result;
}
2016-11-28 03:28:41 +00:00
_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);
}
});
2016-11-28 05:02:12 +00:00
if (data == null)
request.send();
else
request.send(JSON.encode(data));
2016-11-28 03:28:41 +00:00
return completer.future;
}
2016-06-25 18:37:49 +00:00
/// Queries an Angel server via REST.
class Rest extends Angel {
2016-11-28 03:28:41 +00:00
String _authToken;
Rest(String basePath) : super(basePath);
@override
Future<AngelAuthResult> authenticate(
{String type: auth_types.LOCAL,
credentials,
String authEndpoint: '/auth'}) async {
2016-11-28 03:34:04 +00:00
if (type == null) {
if (window.localStorage.containsKey('user') &&
window.localStorage.containsKey('token')) {
final result = new _AngelAuthResultImpl(
token: JSON.decode(window.localStorage['token']),
data: JSON.decode(window.localStorage['user']));
_authToken = result.token;
return result;
} else {
throw new Exception('Failed to authenticate via localStorage.');
}
}
2016-11-28 03:28:41 +00:00
final url = '$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((_) {
2016-11-28 03:34:04 +00:00
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);
2016-11-28 03:28:41 +00:00
})
..onError.listen((_) {
try {
throw new Exception(
'Request failed with status code ${request.status}.');
} catch (e, st) {
completer.completeError(e, st);
}
});
2016-11-28 05:05:20 +00:00
if (credentials == null)
request.send();
else
request.send(JSON.encode(credentials));
2016-11-28 03:28:41 +00:00
return completer.future;
} else {
throw new Exception('angel_client cannot authenticate as "$type" yet.');
}
}
2016-06-25 18:37:49 +00:00
@override
RestService service(String path, {Type type}) {
String uri = path.replaceAll(new RegExp(r"(^\/)|(\/+$)"), "");
2016-11-28 03:28:41 +00:00
return new _RestServiceImpl(this, "$basePath/$uri");
}
}
abstract class RestService extends Service {
RestService._(String basePath);
}
class _AngelAuthResultImpl implements AngelAuthResult {
final Map<String, dynamic> data = {};
final String token;
_AngelAuthResultImpl({this.token, Map<String, dynamic> data: const {}}) {
this.data.addAll(data ?? {});
2016-06-25 18:37:49 +00:00
}
2016-11-28 03:28:41 +00:00
factory _AngelAuthResultImpl.fromMap(Map data) =>
new _AngelAuthResultImpl(token: data['token'], data: data['data']);
2016-06-25 18:37:49 +00:00
}
/// Queries an Angel service via REST.
2016-11-28 03:28:41 +00:00
class _RestServiceImpl extends RestService {
final Rest app;
String _basePath;
String get basePath => _basePath;
2016-06-25 18:37:49 +00:00
2016-11-28 03:28:41 +00:00
_RestServiceImpl(this.app, String basePath) : super._(basePath) {
_basePath = basePath;
2016-06-25 18:37:49 +00:00
}
_makeBody(data) {
return JSON.encode(data);
}
2016-11-28 03:28:41 +00:00
Future<HttpRequest> buildRequest(String url,
{String method: "POST", bool write: true}) async {
2016-06-25 18:37:49 +00:00
HttpRequest request = new HttpRequest();
2016-11-28 03:28:41 +00:00
request.open(method, url);
2016-06-25 18:37:49 +00:00
request.responseType = "json";
request.setRequestHeader("Accept", "application/json");
2016-11-28 03:28:41 +00:00
if (write) request.setRequestHeader("Content-Type", "application/json");
if (app._authToken != null)
request.setRequestHeader("Authorization", "Bearer ${app._authToken}");
2016-06-25 18:37:49 +00:00
return request;
}
@override
Future<List> index([Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest('$basePath/${_buildQuery(params)}',
method: 'GET', write: false);
return await _send(request);
2016-06-25 18:37:49 +00:00
}
@override
Future read(id, [Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest('$basePath/$id${_buildQuery(params)}',
method: 'GET', write: false);
return await _send(request);
2016-06-25 18:37:49 +00:00
}
@override
Future create(data, [Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest("$basePath/${_buildQuery(params)}");
return await _send(request, _makeBody(data));
2016-06-25 18:37:49 +00:00
}
@override
Future modify(id, data, [Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest("$basePath/$id${_buildQuery(params)}",
method: "PATCH");
return await _send(request, _makeBody(data));
2016-06-25 18:37:49 +00:00
}
@override
Future update(id, data, [Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest("$basePath/$id${_buildQuery(params)}");
return await _send(request, _makeBody(data));
2016-06-25 18:37:49 +00:00
}
@override
Future remove(id, [Map params]) async {
2016-11-28 03:28:41 +00:00
final request = await buildRequest("$basePath/$id${_buildQuery(params)}",
method: "DELETE");
return await _send(request);
2016-06-25 18:37:49 +00:00
}
}