Just needs more test
This commit is contained in:
parent
fb33a99281
commit
876e998445
6 changed files with 109 additions and 17 deletions
21
README.md
21
README.md
|
@ -25,6 +25,27 @@ main() async {
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Adding Handlers within a Controller**
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'dart:async';
|
||||||
|
import "package:angel_framework/angel_framework.dart";
|
||||||
|
import "package:angel_websocket/server.dart";
|
||||||
|
|
||||||
|
@Expose("/")
|
||||||
|
class MyController extends Controller {
|
||||||
|
@override
|
||||||
|
Future call(AngelBase app) async {
|
||||||
|
var ws = app.container.make(AngelWebSocket);
|
||||||
|
ws.onConnection.listen((WebSocketContext socket) {
|
||||||
|
socket.on["message"].listen((WebSocketEvent e) {
|
||||||
|
socket.send("new_message", { "text": e.data["text"] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
**In the Browser**
|
**In the Browser**
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
|
|
|
@ -9,6 +9,7 @@ export 'package:angel_websocket/angel_websocket.dart';
|
||||||
class WebSocketClient extends Angel {
|
class WebSocketClient extends Angel {
|
||||||
WebSocket _socket;
|
WebSocket _socket;
|
||||||
Map<Pattern, List<WebSocketService>> _services = {};
|
Map<Pattern, List<WebSocketService>> _services = {};
|
||||||
|
WebSocket get _underlyingSocket => _socket;
|
||||||
|
|
||||||
WebSocketClient(String wsEndpoint) : super(wsEndpoint) {
|
WebSocketClient(String wsEndpoint) : super(wsEndpoint) {
|
||||||
_socket = new WebSocket(wsEndpoint);
|
_socket = new WebSocket(wsEndpoint);
|
||||||
|
@ -67,6 +68,10 @@ class WebSocketClient extends Angel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void send(String eventName, data) {
|
||||||
|
_socket.send(JSON.encode({"eventName": eventName, "data": data}));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Service service(Pattern path, {Type type}) {
|
Service service(Pattern path, {Type type}) {
|
||||||
var service =
|
var service =
|
||||||
|
@ -159,16 +164,11 @@ class WebSocketService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
_serialize(WebSocketAction action) {
|
_serialize(WebSocketAction action) {
|
||||||
var data = {
|
var data = {"id": action.id, "eventName": action.eventName};
|
||||||
"id": action.id,
|
|
||||||
"eventName": action.eventName
|
|
||||||
};
|
|
||||||
|
|
||||||
if (action.data != null)
|
if (action.data != null) data["data"] = action.data;
|
||||||
data["data"] = action.data;
|
|
||||||
|
|
||||||
if (action.params != null)
|
if (action.params != null) data["params"] = action.params;
|
||||||
data["params"] = action.params;
|
|
||||||
|
|
||||||
return JSON.encode(data);
|
return JSON.encode(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ export 'package:angel_websocket/angel_websocket.dart';
|
||||||
class WebSocketClient extends Angel {
|
class WebSocketClient extends Angel {
|
||||||
WebSocket _socket;
|
WebSocket _socket;
|
||||||
Map<Pattern, List<WebSocketService>> _services = {};
|
Map<Pattern, List<WebSocketService>> _services = {};
|
||||||
|
WebSocket get underlyingSocket => _socket;
|
||||||
|
|
||||||
WebSocketClient(String wsEndpoint) : super(wsEndpoint);
|
WebSocketClient(String wsEndpoint) : super(wsEndpoint);
|
||||||
|
|
||||||
|
@ -70,6 +71,13 @@ class WebSocketClient extends Angel {
|
||||||
_socket.listen(onData);
|
_socket.listen(onData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void send(String eventName, data) {
|
||||||
|
_socket.add(JSON.encode({
|
||||||
|
"eventName": eventName,
|
||||||
|
"data": data
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Service service(Pattern path, {Type type}) {
|
Service service(Pattern path, {Type type}) {
|
||||||
var service =
|
var service =
|
||||||
|
|
|
@ -11,8 +11,6 @@ export 'angel_websocket.dart';
|
||||||
|
|
||||||
part 'websocket_context.dart';
|
part 'websocket_context.dart';
|
||||||
|
|
||||||
final AngelWebSocket websocket = new AngelWebSocket("/ws");
|
|
||||||
|
|
||||||
class Realtime {
|
class Realtime {
|
||||||
const Realtime();
|
const Realtime();
|
||||||
}
|
}
|
||||||
|
@ -20,9 +18,12 @@ class Realtime {
|
||||||
class AngelWebSocket extends AngelPlugin {
|
class AngelWebSocket extends AngelPlugin {
|
||||||
Angel _app;
|
Angel _app;
|
||||||
List<WebSocket> _clients = [];
|
List<WebSocket> _clients = [];
|
||||||
|
StreamController<WebSocketContext> _onConnection =
|
||||||
|
new StreamController<WebSocketContext>.broadcast();
|
||||||
List<WebSocket> get clients => new List.from(_clients, growable: false);
|
List<WebSocket> get clients => new List.from(_clients, growable: false);
|
||||||
List<String> servicesAlreadyWired = [];
|
List<String> servicesAlreadyWired = [];
|
||||||
String endpoint;
|
String endpoint;
|
||||||
|
Stream<WebSocketContext> get onConnection => _onConnection.stream;
|
||||||
|
|
||||||
AngelWebSocket(String this.endpoint);
|
AngelWebSocket(String this.endpoint);
|
||||||
|
|
||||||
|
@ -113,6 +114,7 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
|
|
||||||
onData(WebSocketContext socket, data) async {
|
onData(WebSocketContext socket, data) async {
|
||||||
try {
|
try {
|
||||||
|
socket._onData.add(data);
|
||||||
var fromJson = JSON.decode(data);
|
var fromJson = JSON.decode(data);
|
||||||
var action = new WebSocketAction(
|
var action = new WebSocketAction(
|
||||||
id: fromJson['id'],
|
id: fromJson['id'],
|
||||||
|
@ -126,12 +128,32 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
throw new AngelHttpException.BadRequest();
|
throw new AngelHttpException.BadRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fromJson is Map && fromJson.containsKey("eventName")) {
|
||||||
|
socket._onAll.add(fromJson);
|
||||||
|
socket.on._getStreamForEvent(fromJson["eventName"].toString()).add(fromJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.eventName.contains("::")) {
|
||||||
|
var split = action.eventName.split("::");
|
||||||
|
|
||||||
|
if (split.length >= 2) {
|
||||||
|
if ([
|
||||||
|
"index",
|
||||||
|
"read",
|
||||||
|
"create",
|
||||||
|
"modify",
|
||||||
|
"update",
|
||||||
|
"remove"
|
||||||
|
].contains(split[1])) {
|
||||||
var event = handleAction(action, socket);
|
var event = handleAction(action, socket);
|
||||||
if (event is Future) event = await event;
|
if (event is Future) event = await event;
|
||||||
|
|
||||||
if (event is WebSocketEvent) {
|
if (event is WebSocketEvent) {
|
||||||
batchEvent(event);
|
batchEvent(event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Send an error
|
// Send an error
|
||||||
if (e is AngelHttpException)
|
if (e is AngelHttpException)
|
||||||
|
@ -182,6 +204,7 @@ class AngelWebSocket extends AngelPlugin {
|
||||||
var socket = new WebSocketContext(ws, req, res);
|
var socket = new WebSocketContext(ws, req, res);
|
||||||
await onConnect(socket);
|
await onConnect(socket);
|
||||||
|
|
||||||
|
_onConnection.add(socket);
|
||||||
req.params['socket'] = socket;
|
req.params['socket'] = socket;
|
||||||
|
|
||||||
ws.listen((data) {
|
ws.listen((data) {
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
part of angel_websocket.server;
|
part of angel_websocket.server;
|
||||||
|
|
||||||
class WebSocketContext {
|
class WebSocketContext {
|
||||||
|
StreamController<Map> _onAll = new StreamController<Map>.broadcast();
|
||||||
|
StreamController _onData = new StreamController.broadcast();
|
||||||
|
_WebSocketEventTable on = new _WebSocketEventTable();
|
||||||
|
Stream<Map> get onAll => _onAll.stream;
|
||||||
|
Stream get onData => _onData.stream;
|
||||||
WebSocket underlyingSocket;
|
WebSocket underlyingSocket;
|
||||||
RequestContext requestContext;
|
RequestContext requestContext;
|
||||||
ResponseContext responseContext;
|
ResponseContext responseContext;
|
||||||
|
@ -15,3 +20,15 @@ class WebSocketContext {
|
||||||
|
|
||||||
sendError(AngelHttpException error) => send("error", error);
|
sendError(AngelHttpException error) => send("error", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _WebSocketEventTable {
|
||||||
|
Map<String, StreamController<Map>> _handlers = {};
|
||||||
|
|
||||||
|
StreamController<Map> _getStreamForEvent(eventName) {
|
||||||
|
if (!_handlers.containsKey(eventName))
|
||||||
|
_handlers[eventName] = new StreamController<Map>.broadcast();
|
||||||
|
return _handlers[eventName];
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Map> operator [](String key) => _getStreamForEvent(key).stream;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:angel_framework/angel_framework.dart' as server;
|
import 'package:angel_framework/angel_framework.dart' as server;
|
||||||
import 'package:angel_websocket/cli.dart' as client;
|
import 'package:angel_websocket/cli.dart' as client;
|
||||||
|
@ -10,7 +11,9 @@ main() {
|
||||||
server.Angel app;
|
server.Angel app;
|
||||||
client.WebSocketClient clientApp;
|
client.WebSocketClient clientApp;
|
||||||
client.WebSocketService clientTodos;
|
client.WebSocketService clientTodos;
|
||||||
|
Stream<Map> customEventStream;
|
||||||
WebSocket socket;
|
WebSocket socket;
|
||||||
|
AngelWebSocket webSocket = new AngelWebSocket("/ws");
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
app = new server.Angel();
|
app = new server.Angel();
|
||||||
|
@ -21,7 +24,18 @@ main() {
|
||||||
.service("api/todos")
|
.service("api/todos")
|
||||||
.create(new Todo(text: "Clean your room", when: "now"));
|
.create(new Todo(text: "Clean your room", when: "now"));
|
||||||
|
|
||||||
await app.configure(websocket);
|
await app.configure(webSocket);
|
||||||
|
await app.configure((server.Angel app) async {
|
||||||
|
AngelWebSocket ws = app.container.make(AngelWebSocket);
|
||||||
|
|
||||||
|
ws.onConnection.listen((WebSocketContext socket) {
|
||||||
|
socket.onData.listen((data) {
|
||||||
|
print("Data: $data");
|
||||||
|
});
|
||||||
|
|
||||||
|
customEventStream = socket.on["custom"];
|
||||||
|
});
|
||||||
|
});
|
||||||
await app.configure(startTestServer);
|
await app.configure(startTestServer);
|
||||||
|
|
||||||
socket = await WebSocket.connect(app.properties["ws_url"]);
|
socket = await WebSocket.connect(app.properties["ws_url"]);
|
||||||
|
@ -36,8 +50,8 @@ main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("find all real-time services", () {
|
test("find all real-time services", () {
|
||||||
print(websocket.servicesAlreadyWired);
|
print(webSocket.servicesAlreadyWired);
|
||||||
expect(websocket.servicesAlreadyWired, equals(["api/todos"]));
|
expect(webSocket.servicesAlreadyWired, equals(["api/todos"]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("index", () async {
|
test("index", () async {
|
||||||
|
@ -67,6 +81,15 @@ main() {
|
||||||
expect(e.data.text, equals(todo.text));
|
expect(e.data.text, equals(todo.text));
|
||||||
expect(e.data.when, equals(todo.when));
|
expect(e.data.when, equals(todo.when));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("custom event via controller", () async {
|
||||||
|
clientApp.send("custom", {"hello": "world"});
|
||||||
|
|
||||||
|
var data = await customEventStream.first;
|
||||||
|
|
||||||
|
expect(data["eventName"], equals("custom"));
|
||||||
|
expect(data["data"]["hello"], equals("world"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Realtime()
|
@Realtime()
|
||||||
|
|
Loading…
Reference in a new issue