diff --git a/README.md b/README.md index 06ed0eb9..015720eb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,67 @@ # angel_websocket WebSocket plugin for Angel. Features JWT support. + + +# Usage + +**Server-side** + +```dart +import "package:angel_framework/angel_framework.dart"; +import "package:angel_websocket/server.dart"; + +main() async { + var app = new Angel(); + await app.configure(new AngelWebSocket("/ws")); +} + +``` + +**In the Browser** + +```dart +import "package:angel_websocket/browser.dart"; + +main() async { + Angel app = new WebSocketClient("/ws"); + var Cars = app.service("api/cars"); + + Cars.onCreated.listen((e) => print("New car: ${e.data}")); + + // Happens asynchronously + Cars.create({"brand": "Toyota"}); +} +``` + +**CLI Client** + +```dart +import "package:angel_framework/angel_framework" as srv; +import "package:angel_websocket/browser.dart"; + +// You can include these in a shared file and access on both client and server +class Car extends srv.Model { + int year; + String brand, make; + + Car({this.year, this.brand, this.make}); + + @override String toString() => "$year $brand $make"; +} + +main() async { + Angel app = new WebSocketClient("/ws"); + var Cars = app.service("api/cars", type: Car); + + Cars.onCreated.listen((e) { + // Automatically deserialized into a car :) + Car car = e.data; + + // I just bought a new 2016 Toyota Camry! + print("I just bought a new $car!"); + }); + + // Happens asynchronously + Cars.create({"year": 2016, "brand": "Toyota", "make": "Camry"}); +} +``` diff --git a/lib/angel_websocket.dart b/lib/angel_websocket.dart index 1690486f..fc058014 100644 --- a/lib/angel_websocket.dart +++ b/lib/angel_websocket.dart @@ -14,4 +14,4 @@ class WebSocketAction { var params; WebSocketAction({String this.id, String this.eventName, this.data, this.params}); -} \ No newline at end of file +} diff --git a/lib/browser.dart b/lib/browser.dart index 56d1fea2..5e208a92 100644 --- a/lib/browser.dart +++ b/lib/browser.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:html'; import 'package:angel_client/angel_client.dart'; import 'package:angel_websocket/angel_websocket.dart'; +export 'package:angel_client/angel_client.dart'; export 'package:angel_websocket/angel_websocket.dart'; class WebSocketClient extends Angel { diff --git a/lib/client.dart b/lib/cli.dart similarity index 98% rename from lib/client.dart rename to lib/cli.dart index a5b74af9..7802d4db 100644 --- a/lib/client.dart +++ b/lib/cli.dart @@ -5,6 +5,8 @@ import 'package:angel_client/angel_client.dart'; import 'package:angel_framework/angel_framework.dart' as srv; import 'package:angel_websocket/angel_websocket.dart'; import 'package:json_god/json_god.dart' as god; +export 'package:angel_client/angel_client.dart'; +export 'package:angel_websocket/angel_websocket.dart'; class WebSocketClient extends Angel { WebSocket _socket; diff --git a/lib/server.dart b/lib/server.dart index f52d0805..6d06b6d1 100644 --- a/lib/server.dart +++ b/lib/server.dart @@ -7,6 +7,7 @@ import 'package:angel_framework/angel_framework.dart'; import 'package:json_god/json_god.dart' as god; import 'package:merge_map/merge_map.dart'; import 'angel_websocket.dart'; +export 'angel_websocket.dart'; part 'websocket_context.dart'; diff --git a/lib/server_old.dart b/lib/server_old.dart deleted file mode 100644 index cf391caf..00000000 --- a/lib/server_old.dart +++ /dev/null @@ -1,120 +0,0 @@ -library angel_websocket.server; - -import 'dart:async'; -import 'dart:io'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:json_god/json_god.dart' as god; -import 'package:uuid/uuid.dart'; -import 'angel_websocket.dart'; - -typedef Future WebSocketFilter(WebsocketContext context); - -List _clients = []; -Uuid _uuid = new Uuid(); - -class WebsocketContext { - WebSocket socket; - RequestContext request; - ResponseContext response; - - WebsocketContext(WebSocket this.socket, RequestContext this.request, - ResponseContext this.response); -} - -_broadcast(WebSocketEvent event) { - String json = god.serialize(event); - _clients.forEach((WebsocketContext client) { - client.socket.add(json); - }); -} - -_onData(Angel app) { - return (data) { - try { - WebSocketAction action = god.deserialize( - data, outputType: WebSocketAction); - - List split = action.eventName.split("::"); - - if (split.length >= 2) { - Service service = app.service(split[0]); - - if (service != null) { - String event = split[1]; - - if (event == "index") { - - } - } - } - } catch (e) { - - } - }; -} - -_onError(e) { - -} - -class websocket { - static Map filters = {}; - - call({List endPoints: const['/ws']}) { - return (Angel app) async { - for (Pattern endPoint in endPoints) { - app.all(endPoint, (RequestContext req, ResponseContext res) async { - if (!WebSocketTransformer.isUpgradeRequest(req.underlyingRequest)) { - res.write("This endpoint is only accessible via WebSockets."); - res.end(); - } else { - res - ..willCloseItself = true - ..end(); - WebSocket socket = await WebSocketTransformer.upgrade( - req.underlyingRequest); - WebsocketContext context = new WebsocketContext(socket, req, res); - _clients.add(context); - - socket.listen(_onData(app), onError: _onError, onDone: () { - _clients.remove(context); - }); - } - }); - - app.services.forEach((Pattern path, Service service) { - if (service is HookedService) { - String pathName = (path is RegExp) ? path.pattern : path; - List dispatchers = [ - service.afterIndexed, - service.afterCreated, - service.afterRead, - service.afterModified, - service.afterUpdated, - service.afterRemoved - ]; - - for (HookedServiceEventDispatcher dispatcher in dispatchers) { - dispatcher.listen((HookedServiceEvent event) async { - bool canContinue = true; - String filterName = "$pathName::${event.eventName}"; - WebSocketFilter filter = filters[filterName]; - - for (WebsocketContext client in _clients) { - if (filter != null) - canContinue = await filter(client); - } - - if (canContinue) { - WebSocketEvent socketEvent = new WebSocketEvent(eventName: filterName, - data: event.result); - _broadcast(socketEvent); - } - }); - } - } - }); - } - }; - } -} \ No newline at end of file diff --git a/lib/websocket_context.dart b/lib/websocket_context.dart index d9c92529..82e88b91 100644 --- a/lib/websocket_context.dart +++ b/lib/websocket_context.dart @@ -14,4 +14,4 @@ class WebSocketContext { } sendError(AngelHttpException error) => send("error", error); -} \ No newline at end of file +} diff --git a/pubspec.yaml b/pubspec.yaml index b5e0a63a..c3cd1f0d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: angel_websocket description: WebSocket plugin for Angel -version: 1.0.0-dev+1 +version: 1.0.0-dev+2 author: thosakwe homepage: https://github.com/angel-dart/angel_websocket dependencies: diff --git a/test/server.dart b/test/server.dart index d74b44bf..f398198c 100644 --- a/test/server.dart +++ b/test/server.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:angel_framework/angel_framework.dart' as server; -import 'package:angel_websocket/client.dart' as client; -import 'package:angel_websocket/angel_websocket.dart'; +import 'package:angel_websocket/cli.dart' as client; import 'package:angel_websocket/server.dart'; import 'package:json_god/json_god.dart' as god; import 'package:test/test.dart';