This commit is contained in:
thosakwe 2016-12-23 20:45:52 -05:00
parent 7d1f0a9c65
commit 96f95f4d42
5 changed files with 51 additions and 23 deletions

View file

@ -1,13 +1,15 @@
# angel_websocket # 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. WebSocket plugin for Angel.
This plugin broadcasts events from hooked services via WebSockets. This plugin broadcasts events from hooked services via WebSockets.
In addition, In addition, it adds itself to the app's IoC container as `AngelWebSocket`, so that it can be used
it adds itself to the app's IoC container as `AngelWebSocket`, so that it can be used
in controllers as well. in controllers as well.
WebSocket contexts are add to `req.params` as `'socket'`. WebSocket contexts are add to `req.properties` as `'socket'`.
# Usage # Usage
@ -55,13 +57,22 @@ class MyController extends WebSocketController {
import "package:angel_websocket/browser.dart"; import "package:angel_websocket/browser.dart";
main() async { main() async {
Angel app = new WebSocketClient("/ws"); Angel app = new WebSockets("/ws");
await app.connect();
var Cars = app.service("api/cars"); var Cars = app.service("api/cars");
Cars.onCreated.listen((e) => print("New car: ${e.data}")); Cars.onCreated.listen((e) => print("New car: ${e.data}"));
// Happens asynchronously // Happens asynchronously
Cars.create({"brand": "Toyota"}); 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 ```dart
import "package:angel_framework/angel_framework" as srv; 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 // You can include these in a shared file and access on both client and server
class Car extends srv.Model { class Car extends srv.Model {
@ -82,9 +93,11 @@ class Car extends srv.Model {
} }
main() async { main() async {
Angel app = new WebSocketClient("/ws"); Angel app = new WebSockets("/ws");
// Wait for WebSocket connection... // Wait for WebSocket connection...
await app.connect(); await app.connect();
var Cars = app.service("api/cars", type: Car); var Cars = app.service("api/cars", type: Car);
Cars.onCreated.listen((e) { Cars.onCreated.listen((e) {

View file

@ -15,7 +15,7 @@ abstract class BaseWebSocketClient extends BaseAngelClient {
WebSocketChannel _socket; WebSocketChannel _socket;
final StreamController _onData = new StreamController(); final StreamController _onData = new StreamController();
final StreamController<WebSocketEvent> _onMessage = final StreamController<WebSocketEvent> _onAllEvents =
new StreamController<WebSocketEvent>(); new StreamController<WebSocketEvent>();
final StreamController<AngelHttpException> _onError = final StreamController<AngelHttpException> _onError =
new StreamController<AngelHttpException>(); new StreamController<AngelHttpException>();
@ -25,6 +25,13 @@ abstract class BaseWebSocketClient extends BaseAngelClient {
_onWebSocketChannelException = _onWebSocketChannelException =
new StreamController<WebSocketChannelException>(); new StreamController<WebSocketChannelException>();
/// Use this to handle events that are not standard.
final WebSocketExtraneousEventHandler on =
new WebSocketExtraneousEventHandler();
/// Fired on all events.
Stream<WebSocketEvent> get onAllEvents => _onAllEvents.stream;
/// A broadcast stream of data coming from the [socket]. /// A broadcast stream of data coming from the [socket].
/// ///
/// Mostly just for internal use. /// Mostly just for internal use.
@ -33,9 +40,6 @@ abstract class BaseWebSocketClient extends BaseAngelClient {
/// Fired on errors. /// Fired on errors.
Stream<AngelHttpException> get onError => _onError.stream; Stream<AngelHttpException> get onError => _onError.stream;
/// Fired on all events.
Stream<WebSocketEvent> get onMessage => _onMessage.stream;
/// Fired whenever an event is fired by a service. /// Fired whenever an event is fired by a service.
Stream<Map<String, WebSocketEvent>> get onServiceEvent => Stream<Map<String, WebSocketEvent>> get onServiceEvent =>
_onServiceEvent.stream; _onServiceEvent.stream;
@ -85,7 +89,11 @@ abstract class BaseWebSocketClient extends BaseAngelClient {
if (json is Map) { if (json is Map) {
var event = new WebSocketEvent.fromJson(json); 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) { if (event.eventName == EVENT_ERROR) {
var error = new AngelHttpException.fromMap(event.data ?? {}); var error = new AngelHttpException.fromMap(event.data ?? {});
@ -149,10 +157,6 @@ class BaseWebSocketService extends Service {
final StreamController<WebSocketEvent> _onRemoved = final StreamController<WebSocketEvent> _onRemoved =
new StreamController<WebSocketEvent>(); new StreamController<WebSocketEvent>();
/// Use this to handle events that are not standard.
final WebSocketExtraneousEventHandler on =
new WebSocketExtraneousEventHandler();
/// Fired on all events. /// Fired on all events.
Stream<WebSocketEvent> get onAllEvents => _onAllEvents.stream; Stream<WebSocketEvent> get onAllEvents => _onAllEvents.stream;
@ -199,7 +203,6 @@ class BaseWebSocketService extends Service {
var transformed = transformEvent(event); var transformed = transformEvent(event);
_onAllEvents.add(event); _onAllEvents.add(event);
on._getStream(event.eventName).add(event);
switch (event.eventName) { switch (event.eventName) {
case EVENT_INDEXED: case EVENT_INDEXED:
@ -284,7 +287,7 @@ class WebSocketExtraneousEventHandler {
return _events[index]; return _events[index];
} }
operator [](String index) { Stream<WebSocketEvent> operator [](String index) {
if (_events[index] == null) if (_events[index] == null)
_events[index] = new StreamController<WebSocketEvent>(); _events[index] = new StreamController<WebSocketEvent>();

View file

@ -2,7 +2,7 @@ name: angel_websocket
description: WebSocket plugin for Angel description: WebSocket plugin for Angel
environment: environment:
sdk: ">=1.19.0" sdk: ">=1.19.0"
version: 1.0.0-dev+5 version: 1.0.0-dev+6
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_websocket homepage: https://github.com/angel-dart/angel_websocket
dependencies: dependencies:

View file

@ -5,13 +5,24 @@ class Game {
final String playerOne, playerTwo; final String playerOne, playerTwo;
const Game({this.playerOne, this.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') @Expose('/game')
class GameController extends WebSocketController { class GameController extends WebSocketController {
@ExposeWs('search') @ExposeWs('search')
search(WebSocketContext socket) async { search(WebSocketContext socket) async {
print('OMG ok'); print('User is searching for a game...');
socket.send('searched', 'poop'); socket.send('searched', JOHN_VS_BOB);
} }
} }

View file

@ -55,8 +55,9 @@ main() {
group('controller.io', () { group('controller.io', () {
test('search', () async { test('search', () async {
client.send('search', new ws.WebSocketAction()); client.send('search', new ws.WebSocketAction());
var search = await client.onData.first; var search = await client.on['searched'].first;
print('First: $search'); print('Searched: ${search.data}');
expect(new Game.fromJson(search.data), equals(JOHN_VS_BOB));
}); });
}); });
} }