part of angel_framework.http; /// Wraps another service in a service that broadcasts events on actions. class HookedService extends Service { StreamController _beforeIndexed = new StreamController.broadcast(); StreamController _beforeRead = new StreamController.broadcast(); StreamController _beforeCreated = new StreamController.broadcast(); StreamController _beforeModified = new StreamController.broadcast(); StreamController _beforeUpdated = new StreamController.broadcast(); StreamController _beforeRemoved = new StreamController.broadcast(); Stream get beforeIndexed => _beforeIndexed.stream; Stream get beforeRead => _beforeRead.stream; Stream get beforeCreated => _beforeCreated.stream; Stream get beforeModified => _beforeModified.stream; Stream get beforeUpdated => _beforeUpdated.stream; Stream get beforeRemoved => _beforeRemoved.stream; StreamController _afterIndexed = new StreamController.broadcast(); StreamController _afterRead = new StreamController.broadcast(); StreamController _afterCreated = new StreamController.broadcast(); StreamController _afterModified = new StreamController.broadcast(); StreamController _afterUpdated = new StreamController.broadcast(); StreamController _afterRemoved = new StreamController.broadcast(); Stream get afterIndexed => _afterIndexed.stream; Stream get afterRead => _afterRead.stream; Stream get afterCreated => _afterCreated.stream; Stream get afterModified => _afterModified.stream; Stream get afterUpdated => _afterUpdated.stream; Stream get afterRemoved => _afterRemoved.stream; final Service inner; HookedService(Service this.inner); @override Future index([Map params]) async { HookedServiceEvent before = new HookedServiceEvent._base(inner, params: params); _beforeIndexed.add(before); if (before._canceled) { HookedServiceEvent after = new HookedServiceEvent._base(inner, params: params, result: before.result); _afterIndexed.add(after); return before.result; } List result = await inner.index(params); HookedServiceEvent after = new HookedServiceEvent._base(inner, params: params, result: result); _afterIndexed.add(after); return result; } @override Future read(id, [Map params]) async { var retrieved = await inner.read(id, params); _afterRead.add(retrieved); return retrieved; } @override Future create(data, [Map params]) async { var created = await inner.create(data, params); _afterCreated.add(created); return created; } @override Future modify(id, data, [Map params]) async { var modified = await inner.modify(id, data, params); _afterUpdated.add(modified); return modified; } @override Future update(id, data, [Map params]) async { var updated = await inner.update(id, data, params); _afterUpdated.add(updated); return updated; } @override Future remove(id, [Map params]) async { var removed = await inner.remove(id, params); _afterRemoved.add(removed); return removed; } } /// Fired when a hooked service is invoked. class HookedServiceEvent { /// Use this to end processing of an event. void cancel(result) { _canceled = true; _result = result; } bool _canceled = false; var id; var data; Map params; var _result; get result => _result; /// The inner service whose method was hooked. Service service; HookedServiceEvent._base(Service this.service, {this.id, this.data, Map this.params: const{}, result}) { _result = result; } }