This commit is contained in:
thosakwe 2017-01-28 16:08:07 -05:00
parent 0adfdbeb59
commit 19af9b6e5f
6 changed files with 135 additions and 61 deletions

View file

@ -1,6 +1,6 @@
# angel_framework # angel_framework
[![pub 1.0.0-dev.50](https://img.shields.io/badge/pub-1.0.0--dev.50-red.svg)](https://pub.dartlang.org/packages/angel_framework) [![pub 1.0.0-dev.51](https://img.shields.io/badge/pub-1.0.0--dev.51-red.svg)](https://pub.dartlang.org/packages/angel_framework)
[![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework) [![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework)
Core libraries for the Angel Framework. Core libraries for the Angel Framework.

21
lib/hooks.dart Normal file
View file

@ -0,0 +1,21 @@
/// Easy helper hooks.
library angel_framework.hooks;
import 'package:json_god/json_god.dart' as god;
import 'angel_framework.dart';
/// Transforms `e.data` into JSON-friendly data, i.e. a Map.
HookedServiceEventListener toJson() {
return (HookedServiceEvent e) {
if (e.data != null && e.data is! Map) e.data = god.serializeObject(e.data);
};
}
/// Transforms `e.data` into an instance of the given [type],
/// if it is not already.
HookedServiceEventListener toType(Type type) {
return (HookedServiceEvent e) {
if (e.data != null && e.data.runtimeType != type)
e.data = god.deserializeDatum(e.data, outputType: type);
};
}

View file

@ -112,71 +112,72 @@ class AngelHttpException implements Exception {
factory AngelHttpException.unavailable({String message: '503 Unavailable'}) => factory AngelHttpException.unavailable({String message: '503 Unavailable'}) =>
new AngelHttpException(null, message: message, statusCode: 503); new AngelHttpException(null, message: message, statusCode: 503);
/// Throws a 400 Bad Request error, including an optional arrray of (validation?) /// DEPRECATED: Use lowercase constructor instead.
/// errors you specify. @deprecated
@Deprecated('Use lowercase constructor instead')
factory AngelHttpException.BadRequest( factory AngelHttpException.BadRequest(
{String message: '400 Bad Request', List<String> errors: const []}) => {String message: '400 Bad Request', List<String> errors: const []}) =>
new AngelHttpException(null, new AngelHttpException(null,
message: message, errors: errors, statusCode: 400); message: message, errors: errors, statusCode: 400);
/// Throws a 401 Not Authenticated error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.NotAuthenticated( factory AngelHttpException.NotAuthenticated(
{String message: '401 Not Authenticated'}) => {String message: '401 Not Authenticated'}) =>
new AngelHttpException(null, message: message, statusCode: 401); new AngelHttpException(null, message: message, statusCode: 401);
/// Throws a 402 Payment Required error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.PaymentRequired( factory AngelHttpException.PaymentRequired(
{String message: '402 Payment Required'}) => {String message: '402 Payment Required'}) =>
new AngelHttpException(null, message: message, statusCode: 402); new AngelHttpException(null, message: message, statusCode: 402);
/// Throws a 403 Forbidden error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.Forbidden({String message: '403 Forbidden'}) => factory AngelHttpException.Forbidden({String message: '403 Forbidden'}) =>
new AngelHttpException(null, message: message, statusCode: 403); new AngelHttpException(null, message: message, statusCode: 403);
/// Throws a 404 Not Found error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.NotFound({String message: '404 Not Found'}) => factory AngelHttpException.NotFound({String message: '404 Not Found'}) =>
new AngelHttpException(null, message: message, statusCode: 404); new AngelHttpException(null, message: message, statusCode: 404);
/// Throws a 405 Method Not Allowed error. @deprecated
/// DEPRECATED: Use lowercase constructor instead.
factory AngelHttpException.MethodNotAllowed( factory AngelHttpException.MethodNotAllowed(
{String message: '405 Method Not Allowed'}) => {String message: '405 Method Not Allowed'}) =>
new AngelHttpException(null, message: message, statusCode: 405); new AngelHttpException(null, message: message, statusCode: 405);
/// Throws a 406 Not Acceptable error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.NotAcceptable( factory AngelHttpException.NotAcceptable(
{String message: '406 Not Acceptable'}) => {String message: '406 Not Acceptable'}) =>
new AngelHttpException(null, message: message, statusCode: 406); new AngelHttpException(null, message: message, statusCode: 406);
/// Throws a 408 Timeout error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.MethodTimeout({String message: '408 Timeout'}) => factory AngelHttpException.MethodTimeout({String message: '408 Timeout'}) =>
new AngelHttpException(null, message: message, statusCode: 408); new AngelHttpException(null, message: message, statusCode: 408);
/// Throws a 409 Conflict error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.Conflict({String message: '409 Conflict'}) => factory AngelHttpException.Conflict({String message: '409 Conflict'}) =>
new AngelHttpException(null, message: message, statusCode: 409); new AngelHttpException(null, message: message, statusCode: 409);
/// Throws a 422 Not Processable error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.NotProcessable( factory AngelHttpException.NotProcessable(
{String message: '422 Not Processable'}) => {String message: '422 Not Processable'}) =>
new AngelHttpException(null, message: message, statusCode: 422); new AngelHttpException(null, message: message, statusCode: 422);
/// Throws a 501 Not Implemented error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.NotImplemented( factory AngelHttpException.NotImplemented(
{String message: '501 Not Implemented'}) => {String message: '501 Not Implemented'}) =>
new AngelHttpException(null, message: message, statusCode: 501); new AngelHttpException(null, message: message, statusCode: 501);
/// Throws a 503 Unavailable error. /// DEPRECATED: Use lowercase constructor instead.
@Deprecated('Use lowercase constructor instead') @deprecated
factory AngelHttpException.Unavailable({String message: '503 Unavailable'}) => factory AngelHttpException.Unavailable({String message: '503 Unavailable'}) =>
new AngelHttpException(null, message: message, statusCode: 503); new AngelHttpException(null, message: message, statusCode: 503);
} }

View file

@ -176,7 +176,54 @@ class HookedService extends Service {
addHooks(); addHooks();
} }
/// Runs the [listener] before every service method; /// Runs the [listener] before every service method specified.
void before(
Iterable<String> eventNames, HookedServiceEventListener listener) {
eventNames.map((name) {
switch (name) {
case HookedServiceEvent.INDEXED:
return beforeIndexed;
case HookedServiceEvent.READ:
return beforeRead;
case HookedServiceEvent.CREATED:
return beforeCreated;
case HookedServiceEvent.MODIFIED:
return beforeModified;
case HookedServiceEvent.UPDATED:
return beforeUpdated;
case HookedServiceEvent.REMOVED:
return beforeRemoved;
default:
throw new ArgumentError('Invalid service method: ${name}');
}
}).forEach((HookedServiceEventDispatcher dispatcher) =>
dispatcher.listen(listener));
}
/// Runs the [listener] after every service method specified.
void after(Iterable<String> eventNames, HookedServiceEventListener listener) {
eventNames.map((name) {
switch (name) {
case HookedServiceEvent.INDEXED:
return afterIndexed;
case HookedServiceEvent.READ:
return afterRead;
case HookedServiceEvent.CREATED:
return afterCreated;
case HookedServiceEvent.MODIFIED:
return afterModified;
case HookedServiceEvent.UPDATED:
return afterUpdated;
case HookedServiceEvent.REMOVED:
return afterRemoved;
default:
throw new ArgumentError('Invalid service method: ${name}');
}
}).forEach((HookedServiceEventDispatcher dispatcher) =>
dispatcher.listen(listener));
}
/// Runs the [listener] before every service method.
void beforeAll(HookedServiceEventListener listener) { void beforeAll(HookedServiceEventListener listener) {
beforeIndexed.listen(listener); beforeIndexed.listen(listener);
beforeRead.listen(listener); beforeRead.listen(listener);
@ -207,12 +254,12 @@ class HookedService extends Service {
Future<List> index([Map _params]) async { Future<List> index([Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeIndexed._emit( HookedServiceEvent before = await beforeIndexed._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params)); params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await beforeIndexed._emit( HookedServiceEvent after = await beforeIndexed._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params, result: before.result)); params: params, result: before.result));
return after.result; return after.result;
@ -220,7 +267,7 @@ class HookedService extends Service {
List result = await inner.index(params); List result = await inner.index(params);
HookedServiceEvent after = await afterIndexed._emit( HookedServiceEvent after = await afterIndexed._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params, result: result)); params: params, result: result));
return after.result; return after.result;
@ -230,13 +277,13 @@ class HookedService extends Service {
Future read(id, [Map _params]) async { Future read(id, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeRead._emit( HookedServiceEvent before = await beforeRead._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params)); id: id, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterRead._emit( HookedServiceEvent after = await afterRead._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params, result: before.result)); id: id, params: params, result: before.result));
return after.result; return after.result;
@ -244,7 +291,7 @@ class HookedService extends Service {
var result = await inner.read(id, params); var result = await inner.read(id, params);
HookedServiceEvent after = await afterRead._emit( HookedServiceEvent after = await afterRead._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params, result: result)); id: id, params: params, result: result));
return after.result; return after.result;
@ -254,13 +301,13 @@ class HookedService extends Service {
Future create(data, [Map _params]) async { Future create(data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeCreated._emit( HookedServiceEvent before = await beforeCreated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params)); data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterCreated._emit( HookedServiceEvent after = await afterCreated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params, result: before.result)); data: data, params: params, result: before.result));
return after.result; return after.result;
@ -268,7 +315,7 @@ class HookedService extends Service {
var result = await inner.create(data, params); var result = await inner.create(data, params);
HookedServiceEvent after = await afterCreated._emit( HookedServiceEvent after = await afterCreated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params, result: result)); data: data, params: params, result: result));
return after.result; return after.result;
@ -278,13 +325,13 @@ class HookedService extends Service {
Future modify(id, data, [Map _params]) async { Future modify(id, data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeModified._emit( HookedServiceEvent before = await beforeModified._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params)); id: id, data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterModified._emit( HookedServiceEvent after = await afterModified._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params, result: before.result)); id: id, data: data, params: params, result: before.result));
return after.result; return after.result;
@ -292,7 +339,7 @@ class HookedService extends Service {
var result = await inner.modify(id, data, params); var result = await inner.modify(id, data, params);
HookedServiceEvent after = await afterModified._emit( HookedServiceEvent after = await afterModified._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params, result: result)); id: id, data: data, params: params, result: result));
return after.result; return after.result;
@ -302,13 +349,13 @@ class HookedService extends Service {
Future update(id, data, [Map _params]) async { Future update(id, data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeUpdated._emit( HookedServiceEvent before = await beforeUpdated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params)); id: id, data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterUpdated._emit( HookedServiceEvent after = await afterUpdated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params, result: before.result)); id: id, data: data, params: params, result: before.result));
return after.result; return after.result;
@ -316,7 +363,7 @@ class HookedService extends Service {
var result = await inner.update(id, data, params); var result = await inner.update(id, data, params);
HookedServiceEvent after = await afterUpdated._emit( HookedServiceEvent after = await afterUpdated._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params, result: result)); id: id, data: data, params: params, result: result));
return after.result; return after.result;
@ -326,13 +373,13 @@ class HookedService extends Service {
Future remove(id, [Map _params]) async { Future remove(id, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeRemoved._emit( HookedServiceEvent before = await beforeRemoved._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(false, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params)); id: id, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterRemoved._emit( HookedServiceEvent after = await afterRemoved._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params, result: before.result)); id: id, params: params, result: before.result));
return after.result; return after.result;
@ -340,7 +387,7 @@ class HookedService extends Service {
var result = await inner.remove(id, params); var result = await inner.remove(id, params);
HookedServiceEvent after = await afterRemoved._emit( HookedServiceEvent after = await afterRemoved._emit(
new HookedServiceEvent._base(_getRequest(_params), new HookedServiceEvent._base(true, _getRequest(_params),
_getResponse(_params), inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params, result: result)); id: id, params: params, result: result));
return after.result; return after.result;
@ -375,7 +422,7 @@ class HookedService extends Service {
throw new ArgumentError("Invalid service event name: '$eventName'"); throw new ArgumentError("Invalid service event name: '$eventName'");
} }
var ev = new HookedServiceEvent._base(null, null, this, eventName); var ev = new HookedServiceEvent._base(true, null, null, this, eventName);
if (callback != null) await callback(ev); if (callback != null) await callback(ev);
return await dispatcher._emit(ev); return await dispatcher._emit(ev);
} }
@ -399,6 +446,7 @@ class HookedServiceEvent {
bool _canceled = false; bool _canceled = false;
String _eventName; String _eventName;
var _id; var _id;
bool _isAfter;
var data; var data;
Map _params; Map _params;
var _result; var _result;
@ -409,6 +457,10 @@ class HookedServiceEvent {
get id => _id; get id => _id;
bool get isAfter => _isAfter == true;
bool get isBefore => !isAfter;
Map get params => _params; Map get params => _params;
RequestContext get request => _request; RequestContext get request => _request;
@ -420,8 +472,8 @@ class HookedServiceEvent {
/// The inner service whose method was hooked. /// The inner service whose method was hooked.
Service service; Service service;
HookedServiceEvent._base(this._request, this._response, Service this.service, HookedServiceEvent._base(this._isAfter, this._request, this._response,
String this._eventName, Service this.service, String this._eventName,
{id, this.data, Map params, result}) { {id, this.data, Map params, result}) {
_id = id; _id = id;
_params = params ?? {}; _params = params ?? {};

View file

@ -40,32 +40,32 @@ class Service extends Routable {
/// Retrieves all resources. /// Retrieves all resources.
Future<List> index([Map params]) { Future<List> index([Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
/// Retrieves the desired resource. /// Retrieves the desired resource.
Future read(id, [Map params]) { Future read(id, [Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
/// Creates a resource. /// Creates a resource.
Future create(data, [Map params]) { Future create(data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
/// Modifies a resource. /// Modifies a resource.
Future modify(id, data, [Map params]) { Future modify(id, data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
/// Overwrites a resource. /// Overwrites a resource.
Future update(id, data, [Map params]) { Future update(id, data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
/// Removes the given resource. /// Removes the given resource.
Future remove(id, [Map params]) { Future remove(id, [Map params]) {
throw new AngelHttpException.MethodNotAllowed(); throw new AngelHttpException.methodNotAllowed();
} }
void addRoutes() { void addRoutes() {

View file

@ -1,5 +1,5 @@
name: angel_framework name: angel_framework
version: 1.0.0-dev.50 version: 1.0.0-dev.51
description: Core libraries for the Angel framework. description: Core libraries for the Angel framework.
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_framework homepage: https://github.com/angel-dart/angel_framework