/// Browser client library for the Angel framework. library angel_client.browser; import 'dart:async' show Future, Stream, StreamController, StreamSubscription, Timer; import 'dart:html' show CustomEvent, Event, window; import 'dart:convert'; 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'; /// Queries an Angel server via REST. class Rest extends BaseAngelClient { Rest(String basePath) : super(http.BrowserClient(), basePath); @override Future authenticate( {String? type, credentials, String authEndpoint = '/auth', @deprecated String reviveEndpoint = '/auth/token'}) async { if (type == null || type == 'token') { if (!window.localStorage.containsKey('token')) { throw Exception( 'Cannot revive token from localStorage - there is none.'); } var token = json.decode(window.localStorage['token']!); credentials ??= {'token': token}; } 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 Stream authenticateViaPopup(String url, {String eventName = 'token', String? errorMessage}) { var ctrl = StreamController(); var wnd = window.open(url, 'angel_client_auth_popup'); Timer t; StreamSubscription? sub; t = Timer.periodic(Duration(milliseconds: 500), (timer) { if (!ctrl.isClosed) { if (wnd.closed!) { ctrl.addError(AngelHttpException.notAuthenticated( message: errorMessage ?? 'Authentication via popup window failed.')); ctrl.close(); timer.cancel(); sub?.cancel(); } } else { timer.cancel(); } }); sub = window.on[eventName].listen((Event ev) { var e = ev as CustomEvent; if (!ctrl.isClosed) { ctrl.add(e.detail.toString()); t.cancel(); ctrl.close(); sub!.cancel(); } }); return ctrl.stream; } @override Future logout() { window.localStorage.remove('token'); return super.logout(); } }