diff --git a/README.md b/README.md index 5dcef69e..f8999930 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ # angel_websocket +[![1.0.0-dev+6](https://img.shields.io/badge/version-1.0.0--dev+6-red.svg)](https://pub.dartlang.org/packages/angel_websocket) +[![build status](https://travis-ci.org/angel-dart/websocket.svg)](https://travis-ci.org/angel-dart/websocket) + WebSocket plugin for Angel. This plugin broadcasts events from hooked services via WebSockets. -In addition, -it adds itself to the app's IoC container as `AngelWebSocket`, so that it can be used +In addition, it adds itself to the app's IoC container as `AngelWebSocket`, so that it can be used in controllers as well. -WebSocket contexts are add to `req.params` as `'socket'`. +WebSocket contexts are add to `req.properties` as `'socket'`. # Usage @@ -55,13 +57,22 @@ class MyController extends WebSocketController { import "package:angel_websocket/browser.dart"; main() async { - Angel app = new WebSocketClient("/ws"); + Angel app = new WebSockets("/ws"); + await app.connect(); + var Cars = app.service("api/cars"); Cars.onCreated.listen((e) => print("New car: ${e.data}")); // Happens asynchronously Cars.create({"brand": "Toyota"}); + + // Listen for arbitrary events + app.on['custom_event'].listen((event) { + // For example, this might be sent by a + // WebSocketController. + print('Hi!'); + }); } ``` @@ -69,7 +80,7 @@ main() async { ```dart import "package:angel_framework/angel_framework" as srv; -import "package:angel_websocket/browser.dart"; +import "package:angel_websocket/io.dart"; // You can include these in a shared file and access on both client and server class Car extends srv.Model { @@ -82,9 +93,11 @@ class Car extends srv.Model { } main() async { - Angel app = new WebSocketClient("/ws"); + Angel app = new WebSockets("/ws"); + // Wait for WebSocket connection... await app.connect(); + var Cars = app.service("api/cars", type: Car); Cars.onCreated.listen((e) { diff --git a/lib/base_websocket_client.dart b/lib/base_websocket_client.dart index 9cfed9d6..068aeed9 100644 --- a/lib/base_websocket_client.dart +++ b/lib/base_websocket_client.dart @@ -15,7 +15,7 @@ abstract class BaseWebSocketClient extends BaseAngelClient { WebSocketChannel _socket; final StreamController _onData = new StreamController(); - final StreamController _onMessage = + final StreamController _onAllEvents = new StreamController(); final StreamController _onError = new StreamController(); @@ -25,6 +25,13 @@ abstract class BaseWebSocketClient extends BaseAngelClient { _onWebSocketChannelException = new StreamController(); + /// Use this to handle events that are not standard. + final WebSocketExtraneousEventHandler on = + new WebSocketExtraneousEventHandler(); + + /// Fired on all events. + Stream get onAllEvents => _onAllEvents.stream; + /// A broadcast stream of data coming from the [socket]. /// /// Mostly just for internal use. @@ -33,9 +40,6 @@ abstract class BaseWebSocketClient extends BaseAngelClient { /// Fired on errors. Stream get onError => _onError.stream; - /// Fired on all events. - Stream get onMessage => _onMessage.stream; - /// Fired whenever an event is fired by a service. Stream> get onServiceEvent => _onServiceEvent.stream; @@ -85,7 +89,11 @@ abstract class BaseWebSocketClient extends BaseAngelClient { if (json is Map) { var event = new WebSocketEvent.fromJson(json); - _onMessage.add(event); + + if (event.eventName?.isNotEmpty == true) { + _onAllEvents.add(event); + on._getStream(event.eventName).add(event); + } if (event.eventName == EVENT_ERROR) { var error = new AngelHttpException.fromMap(event.data ?? {}); @@ -149,10 +157,6 @@ class BaseWebSocketService extends Service { final StreamController _onRemoved = new StreamController(); - /// Use this to handle events that are not standard. - final WebSocketExtraneousEventHandler on = - new WebSocketExtraneousEventHandler(); - /// Fired on all events. Stream get onAllEvents => _onAllEvents.stream; @@ -199,7 +203,6 @@ class BaseWebSocketService extends Service { var transformed = transformEvent(event); _onAllEvents.add(event); - on._getStream(event.eventName).add(event); switch (event.eventName) { case EVENT_INDEXED: @@ -284,7 +287,7 @@ class WebSocketExtraneousEventHandler { return _events[index]; } - operator [](String index) { + Stream operator [](String index) { if (_events[index] == null) _events[index] = new StreamController(); diff --git a/pubspec.yaml b/pubspec.yaml index f1330363..0390db4f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: angel_websocket description: WebSocket plugin for Angel environment: sdk: ">=1.19.0" -version: 1.0.0-dev+5 +version: 1.0.0-dev+6 author: Tobe O homepage: https://github.com/angel-dart/angel_websocket dependencies: diff --git a/test/controller/common.dart b/test/controller/common.dart index 4739f7d3..d23bbee2 100644 --- a/test/controller/common.dart +++ b/test/controller/common.dart @@ -5,13 +5,24 @@ class Game { final String playerOne, playerTwo; const Game({this.playerOne, this.playerTwo}); + + factory Game.fromJson(Map data) => + new Game(playerOne: data['playerOne'], playerTwo: data['playerTwo']); + + @override + bool operator ==(other) => + other is Game && + other.playerOne == playerOne && + other.playerTwo == playerTwo; } +const Game JOHN_VS_BOB = const Game(playerOne: 'John', playerTwo: 'Bob'); + @Expose('/game') class GameController extends WebSocketController { @ExposeWs('search') search(WebSocketContext socket) async { - print('OMG ok'); - socket.send('searched', 'poop'); + print('User is searching for a game...'); + socket.send('searched', JOHN_VS_BOB); } -} \ No newline at end of file +} diff --git a/test/controller/io_test.dart b/test/controller/io_test.dart index be211bbe..c80a4314 100644 --- a/test/controller/io_test.dart +++ b/test/controller/io_test.dart @@ -55,8 +55,9 @@ main() { group('controller.io', () { test('search', () async { client.send('search', new ws.WebSocketAction()); - var search = await client.onData.first; - print('First: $search'); + var search = await client.on['searched'].first; + print('Searched: ${search.data}'); + expect(new Game.fromJson(search.data), equals(JOHN_VS_BOB)); }); }); }