1.0.4
This commit is contained in:
parent
3564fb4e35
commit
f1ce32d07e
8 changed files with 74 additions and 20 deletions
36
README.md
36
README.md
|
@ -1,6 +1,6 @@
|
||||||
# angel_client
|
# angel_client
|
||||||
|
|
||||||
[](https://pub.dartlang.org/packages/angel_client)
|
[](https://pub.dartlang.org/packages/angel_client)
|
||||||
[](https://travis-ci.org/angel-dart/client)
|
[](https://travis-ci.org/angel-dart/client)
|
||||||
|
|
||||||
Client library for the Angel framework.
|
Client library for the Angel framework.
|
||||||
|
@ -54,3 +54,37 @@ bar() async {
|
||||||
|
|
||||||
Just like on the server, services support `index`, `read`, `create`, `modify`, `update` and
|
Just like on the server, services support `index`, `read`, `create`, `modify`, `update` and
|
||||||
`remove`.
|
`remove`.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
Local auth:
|
||||||
|
```dart
|
||||||
|
var auth = await app.authenticate(type: 'local', credentials: {username: ..., password: ...});
|
||||||
|
print(auth.token);
|
||||||
|
print(auth.user);
|
||||||
|
```
|
||||||
|
|
||||||
|
Revive an existing jwt:
|
||||||
|
```dart
|
||||||
|
Future<AngelAuthResult> reviveJwt(String jwt) {
|
||||||
|
return app.authenticate(credentials: {'token': jwt});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Via Popup:
|
||||||
|
```dart
|
||||||
|
app.authenticateViaPopup('/auth/google').listen((jwt) {
|
||||||
|
// Do something with the JWT
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Resume a session from localStorage (browser only):
|
||||||
|
```dart
|
||||||
|
// Automatically checks for JSON-encoded 'token' in localStorage,
|
||||||
|
// and tries to revive it
|
||||||
|
await app.authenticate();
|
||||||
|
```
|
||||||
|
|
||||||
|
Logout:
|
||||||
|
```dart
|
||||||
|
await app.logout();
|
||||||
|
```
|
1
dart_test.yaml
Normal file
1
dart_test.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# platforms: [vm, content-shell]
|
|
@ -38,6 +38,9 @@ abstract class Angel {
|
||||||
await configurer(this);
|
await configurer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Logs the current user out of the application.
|
||||||
|
Future logout();
|
||||||
|
|
||||||
Service service<T>(String path, {Type type, AngelDeserializer deserializer});
|
Service service<T>(String path, {Type type, AngelDeserializer deserializer});
|
||||||
|
|
||||||
Future<http.Response> delete(String url, {Map<String, String> headers});
|
Future<http.Response> delete(String url, {Map<String, String> headers});
|
||||||
|
|
|
@ -28,6 +28,11 @@ _buildQuery(Map params) {
|
||||||
return '?' + query.join('&');
|
return '?' + query.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _invalid(http.Response response) =>
|
||||||
|
response.statusCode == null ||
|
||||||
|
response.statusCode < 200 ||
|
||||||
|
response.statusCode >= 300;
|
||||||
|
|
||||||
AngelHttpException failure(http.Response response, {error, StackTrace stack}) {
|
AngelHttpException failure(http.Response response, {error, StackTrace stack}) {
|
||||||
try {
|
try {
|
||||||
final json = JSON.decode(response.body);
|
final json = JSON.decode(response.body);
|
||||||
|
@ -68,7 +73,7 @@ abstract class BaseAngelClient extends Angel {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +103,7 @@ abstract class BaseAngelClient extends Angel {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +128,10 @@ abstract class BaseAngelClient extends Angel {
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future logout() async {
|
||||||
|
authToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends a non-streaming [Request] and returns a non-streaming [Response].
|
/// Sends a non-streaming [Request] and returns a non-streaming [Response].
|
||||||
Future<http.Response> sendUnstreamed(
|
Future<http.Response> sendUnstreamed(
|
||||||
String method, url, Map<String, String> headers,
|
String method, url, Map<String, String> headers,
|
||||||
|
@ -230,7 +239,7 @@ class BaseAngelService extends Service {
|
||||||
'GET', '$basePath${_buildQuery(params)}', _readHeaders);
|
'GET', '$basePath${_buildQuery(params)}', _readHeaders);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +257,7 @@ class BaseAngelService extends Service {
|
||||||
'GET', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
'GET', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +273,7 @@ class BaseAngelService extends Service {
|
||||||
'$basePath/${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
'$basePath/${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +289,7 @@ class BaseAngelService extends Service {
|
||||||
'$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
'$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +305,7 @@ class BaseAngelService extends Service {
|
||||||
'$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
'$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +321,7 @@ class BaseAngelService extends Service {
|
||||||
'DELETE', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
'DELETE', '$basePath/$id${_buildQuery(params)}', _readHeaders);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (response.statusCode != 200) {
|
if (_invalid(response)) {
|
||||||
throw failure(response);
|
throw failure(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'dart:convert' show JSON;
|
||||||
import 'dart:html' show CustomEvent, window;
|
import 'dart:html' show CustomEvent, window;
|
||||||
import 'package:http/browser_client.dart' as http;
|
import 'package:http/browser_client.dart' as http;
|
||||||
import 'angel_client.dart';
|
import 'angel_client.dart';
|
||||||
import 'auth_types.dart' as auth_types;
|
// import 'auth_types.dart' as auth_types;
|
||||||
import 'base_angel_client.dart';
|
import 'base_angel_client.dart';
|
||||||
export 'angel_client.dart';
|
export 'angel_client.dart';
|
||||||
|
|
||||||
|
@ -53,13 +53,15 @@ class Rest extends BaseAngelClient {
|
||||||
var ctrl = new StreamController<String>();
|
var ctrl = new StreamController<String>();
|
||||||
var wnd = window.open(url, 'angel_client_auth_popup');
|
var wnd = window.open(url, 'angel_client_auth_popup');
|
||||||
|
|
||||||
new Timer.periodic(new Duration(milliseconds: 500), (timer) {
|
Timer t;
|
||||||
|
t = new Timer.periodic(new Duration(milliseconds: 500), (timer) {
|
||||||
if (!ctrl.isClosed) {
|
if (!ctrl.isClosed) {
|
||||||
if (wnd.closed) {
|
if (wnd.closed) {
|
||||||
ctrl.addError(new AngelHttpException.notAuthenticated(
|
ctrl.addError(new AngelHttpException.notAuthenticated(
|
||||||
message:
|
message:
|
||||||
errorMessage ?? 'Authentication via popup window failed.'));
|
errorMessage ?? 'Authentication via popup window failed.'));
|
||||||
ctrl.close();
|
ctrl.close();
|
||||||
|
timer.cancel();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
|
@ -68,10 +70,17 @@ class Rest extends BaseAngelClient {
|
||||||
window.on[eventName ?? 'token'].listen((CustomEvent e) {
|
window.on[eventName ?? 'token'].listen((CustomEvent e) {
|
||||||
if (!ctrl.isClosed) {
|
if (!ctrl.isClosed) {
|
||||||
ctrl.add(e.detail);
|
ctrl.add(e.detail);
|
||||||
|
t.cancel();
|
||||||
ctrl.close();
|
ctrl.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return ctrl.stream;
|
return ctrl.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future logout() {
|
||||||
|
window.localStorage.remove('token');
|
||||||
|
return super.logout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: angel_client
|
name: angel_client
|
||||||
version: 1.0.3
|
version: 1.0.4
|
||||||
description: Client library for the Angel framework.
|
description: Client library for the Angel framework.
|
||||||
author: Tobe O <thosakwe@gmail.com>
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
homepage: https://github.com/angel-dart/angel_client
|
homepage: https://github.com/angel-dart/angel_client
|
||||||
|
|
|
@ -6,8 +6,7 @@ import 'for_browser_tests.dart';
|
||||||
main() {
|
main() {
|
||||||
test("list todos", () async {
|
test("list todos", () async {
|
||||||
var channel = spawnHybridCode(SERVER);
|
var channel = spawnHybridCode(SERVER);
|
||||||
int port = await channel.stream.first;
|
String url = await channel.stream.first;
|
||||||
var url = "http://localhost:$port";
|
|
||||||
print(url);
|
print(url);
|
||||||
var app = new Rest(url);
|
var app = new Rest(url);
|
||||||
var todoService = app.service("todos");
|
var todoService = app.service("todos");
|
||||||
|
@ -18,8 +17,7 @@ main() {
|
||||||
|
|
||||||
test('create todos', () async {
|
test('create todos', () async {
|
||||||
var channel = spawnHybridCode(SERVER);
|
var channel = spawnHybridCode(SERVER);
|
||||||
int port = await channel.stream.first;
|
String url = await channel.stream.first;
|
||||||
var url = "http://localhost:$port";
|
|
||||||
print(url);
|
print(url);
|
||||||
var app = new Rest(url);
|
var app = new Rest(url);
|
||||||
var todoService = app.service("todos");
|
var todoService = app.service("todos");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const String SERVER = '''
|
const String SERVER = '''
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import "package:angel_framework/angel_framework.dart";
|
import "package:angel_framework/angel_framework.dart";
|
||||||
import "package:angel_framework/src/defs.dart";
|
import "package:angel_framework/common.dart";
|
||||||
import 'package:stream_channel/stream_channel.dart';
|
import 'package:stream_channel/stream_channel.dart';
|
||||||
|
|
||||||
hybridMain(StreamChannel channel) async {
|
hybridMain(StreamChannel channel) async {
|
||||||
|
@ -12,15 +12,15 @@ hybridMain(StreamChannel channel) async {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use("/todos", new MemoryService<Todo>());
|
app.use("/todos", new TypedService<Todo>(new MapService()));
|
||||||
|
|
||||||
var server = await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
var server = await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||||
|
|
||||||
print("Server up; listening at http://localhost:\${server.port}");
|
print("Server up; listening at http://localhost:\${server.port}");
|
||||||
channel.sink.add(server.port);
|
channel.sink.add('http://\${server.address.address}:\${server.port}');
|
||||||
}
|
}
|
||||||
|
|
||||||
class Todo extends MemoryModel {
|
class Todo extends Model {
|
||||||
String hello;
|
String hello;
|
||||||
|
|
||||||
Todo({int id, this.hello}) {
|
Todo({int id, this.hello}) {
|
||||||
|
|
Loading…
Reference in a new issue