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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - + - - + + + + + - - - @@ -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)); + }); }