diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
index 299eecf0..36d08e55 100644
--- a/.idea/libraries/Dart_Packages.xml
+++ b/.idea/libraries/Dart_Packages.xml
@@ -5,398 +5,398 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index fd63bed5..406d4377 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 6568d145..9bf5a491 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -1,11 +1,17 @@
-
+
+
+
-
+
+
+
+
+
@@ -26,35 +32,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -72,8 +95,8 @@
-
-
+
+
@@ -81,6 +104,11 @@
+
+
+ BEFORE
+
+
@@ -89,6 +117,10 @@
+
+
+
+
@@ -101,10 +133,10 @@
DEFINITION_ORDER
-
-
-
-
+
+
+
+
@@ -124,25 +156,27 @@
+
+
-
+
-
+
-
+
-
+
@@ -152,11 +186,11 @@
-
+
-
+
@@ -170,11 +204,11 @@
-
+
-
+
@@ -192,8 +226,6 @@
-
-
@@ -208,18 +240,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -279,6 +300,13 @@
false
+
+
+
+
+
+
+
@@ -292,6 +320,7 @@
1481236071442
+
1481237183504
@@ -303,33 +332,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
+
+
+
+
-
-
-
@@ -340,13 +401,30 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -389,24 +467,48 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -414,13 +516,21 @@
-
-
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 1fd13365..90753e44 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# angel_framework
-[![pub 1.0.0-dev.30](https://img.shields.io/badge/pub-1.0.0--dev.30-red.svg)](https://pub.dartlang.org/packages/angel_framework)
+[![pub 1.0.0-dev.31](https://img.shields.io/badge/pub-1.0.0--dev.31-red.svg)](https://pub.dartlang.org/packages/angel_framework)
![build status](https://travis-ci.org/angel-dart/framework.svg)
Core libraries for the Angel Framework.
\ No newline at end of file
diff --git a/lib/src/http/hooked_service.dart b/lib/src/http/hooked_service.dart
index 22d7c8e1..2e5eccdb 100644
--- a/lib/src/http/hooked_service.dart
+++ b/lib/src/http/hooked_service.dart
@@ -39,6 +39,41 @@ class HookedService extends Service {
if (inner.app != null) this.app = inner.app;
}
+ void addHooks() {
+ Hooks hooks = getAnnotation(inner, Hooks);
+ final before = [];
+ final after = [];
+
+ if (hooks != null) {
+ before.addAll(hooks.before);
+ after.addAll(hooks.after);
+ }
+
+ void applyListeners(Function fn, HookedServiceEventDispatcher dispatcher,
+ [bool isAfter]) {
+ Hooks hooks = getAnnotation(fn, Hooks);
+ final listeners = []..addAll(isAfter == true ? after : before);
+
+ if (hooks != null)
+ listeners.addAll(isAfter == true ? hooks.after : hooks.before);
+
+ listeners.forEach(dispatcher.listen);
+ }
+
+ applyListeners(inner.index, beforeIndexed);
+ applyListeners(inner.read, beforeRead);
+ applyListeners(inner.created, beforeCreated);
+ applyListeners(inner.modify, beforeModified);
+ applyListeners(inner.updated, beforeUpdated);
+ applyListeners(inner.removed, beforeRemoved);
+ applyListeners(inner.index, afterIndexed, true);
+ applyListeners(inner.read, afterRead, true);
+ applyListeners(inner.created, afterCreated, true);
+ applyListeners(inner.modify, afterModified, true);
+ applyListeners(inner.updated, afterUpdated, true);
+ applyListeners(inner.removed, afterRemoved, true);
+ }
+
@override
void addRoutes() {
// Set up our routes. We still need to copy middleware from inner service
@@ -59,7 +94,10 @@ class HookedService extends Service {
..addAll((indexMiddleware == null) ? [] : indexMiddleware.handlers));
Middleware createMiddleware = getAnnotation(inner.create, Middleware);
- post('/', (req, res) async => await this.create(req.body, mergeMap([req.query, restProvider])),
+ post(
+ '/',
+ (req, res) async =>
+ await this.create(req.body, mergeMap([req.query, restProvider])),
middleware: []
..addAll(handlers)
..addAll(
@@ -70,7 +108,7 @@ class HookedService extends Service {
get(
'/:id',
(req, res) async => await this
- .read(req.params['id'], mergeMap([req.query, restProvider])),
+ .read(req.params['id'], mergeMap([req.query, restProvider])),
middleware: []
..addAll(handlers)
..addAll((readMiddleware == null) ? [] : readMiddleware.handlers));
@@ -78,8 +116,8 @@ class HookedService extends Service {
Middleware modifyMiddleware = getAnnotation(inner.modify, Middleware);
patch(
'/:id',
- (req, res) async =>
- await this.modify(req.params['id'], req.body, mergeMap([req.query, restProvider])),
+ (req, res) async => await this.modify(
+ req.params['id'], req.body, mergeMap([req.query, restProvider])),
middleware: []
..addAll(handlers)
..addAll(
@@ -88,8 +126,8 @@ class HookedService extends Service {
Middleware updateMiddleware = getAnnotation(inner.update, Middleware);
post(
'/:id',
- (req, res) async =>
- await this.update(req.params['id'], req.body, mergeMap([req.query, restProvider])),
+ (req, res) async => await this.update(
+ req.params['id'], req.body, mergeMap([req.query, restProvider])),
middleware: []
..addAll(handlers)
..addAll(
@@ -99,11 +137,13 @@ class HookedService extends Service {
delete(
'/:id',
(req, res) async => await this
- .remove(req.params['id'], mergeMap([req.query, restProvider])),
+ .remove(req.params['id'], mergeMap([req.query, restProvider])),
middleware: []
..addAll(handlers)
..addAll(
(removeMiddleware == null) ? [] : removeMiddleware.handlers));
+
+ addHooks();
}
@override
diff --git a/lib/src/http/metadata.dart b/lib/src/http/metadata.dart
index 1e96c449..194b0306 100644
--- a/lib/src/http/metadata.dart
+++ b/lib/src/http/metadata.dart
@@ -1,10 +1,12 @@
library angel_framework.http.metadata;
+import 'hooked_service.dart' show HookedServiceEventListener;
+
/// Annotation to map middleware onto a handler.
class Middleware {
final List handlers;
- const Middleware(List this.handlers);
+ const Middleware(this.handlers);
}
/// Annotation to set a service up to release hooks on every action.
@@ -12,6 +14,15 @@ class Hooked {
const Hooked();
}
+/// Attaches hooks to a [HookedService].
+class Hooks {
+ final List before;
+ final List after;
+
+ const Hooks({this.before: const [], this.after: const []});
+}
+
+/// Exposes a [Controller] to the Internet.
class Expose {
final String method;
final Pattern path;
@@ -19,9 +30,9 @@ class Expose {
final String as;
final List allowNull;
- const Expose(Pattern this.path,
- {String this.method: "GET",
- List this.middleware: const [],
- String this.as: null,
- List this.allowNull: const[]});
-}
\ No newline at end of file
+ const Expose(this.path,
+ {this.method: "GET",
+ this.middleware: const [],
+ this.as: null,
+ this.allowNull: const []});
+}
diff --git a/lib/src/http/routable.dart b/lib/src/http/routable.dart
index 2bc7f104..16c3ef87 100644
--- a/lib/src/http/routable.dart
+++ b/lib/src/http/routable.dart
@@ -11,6 +11,7 @@ import 'metadata.dart';
import 'request_context.dart';
import 'response_context.dart';
import 'service.dart';
+
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
/// A function that intercepts a request and determines whether handling of it should continue.
diff --git a/pubspec.yaml b/pubspec.yaml
index 6081107b..dacc6765 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
name: angel_framework
-version: 1.0.0-dev.30
+version: 1.0.0-dev.31
description: Core libraries for the Angel framework.
author: Tobe O
homepage: https://github.com/angel-dart/angel_framework
environment:
- sdk: ">=1.18.0"
+ sdk: ">=1.19.0"
dependencies:
angel_route: ^1.0.0-dev
body_parser: ^1.0.0-dev
diff --git a/test/common.dart b/test/common.dart
index cb9ffe1e..97f7c0b1 100644
--- a/test/common.dart
+++ b/test/common.dart
@@ -1,6 +1,6 @@
library angel_framework.test.common;
-import 'package:angel_framework/src/defs.dart';
+import 'package:angel_framework/angel_framework.dart';
class Todo extends MemoryModel {
String text;
@@ -8,3 +8,16 @@ class Todo extends MemoryModel {
Todo({String this.text, String this.over});
}
+
+incrementTodoTimes(e) {
+ IncrementService.TIMES++;
+}
+
+@Hooks(before: const [incrementTodoTimes])
+class IncrementService extends Service {
+ static int TIMES = 0;
+
+ @override
+ @Hooks(after: const [incrementTodoTimes])
+ index([params]) async => [];
+}
diff --git a/test/hooked_test.dart b/test/hooked_test.dart
index 42ea966b..471ff17d 100644
--- a/test/hooked_test.dart
+++ b/test/hooked_test.dart
@@ -18,12 +18,12 @@ main() {
HookedService Todos;
setUp(() async {
- app = new Angel(debug: true);
+ app = new Angel();
client = new http.Client();
app.use('/todos', new MemoryService());
Todos = app.service("todos");
- app.dumpTree(showMatchers: true);
+ // app.dumpTree(showMatchers: true);
server = await app.startServer();
url = "http://${app.httpServer.address.host}:${app.httpServer.port}";
@@ -87,4 +87,12 @@ main() {
List result = god.deserialize(response.body);
expect(result[0]["angel"], equals("framework"));
});
+
+ test('metadata', () async {
+ final service = new HookedService(new IncrementService())..addHooks();
+ expect(service.inner, isNot(new isInstanceOf()));
+ IncrementService.TIMES = 0;
+ await service.index();
+ expect(IncrementService.TIMES, equals(2));
+ });
}