51
This commit is contained in:
parent
0adfdbeb59
commit
19af9b6e5f
6 changed files with 135 additions and 61 deletions
|
@ -1,6 +1,6 @@
|
|||
# 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)
|
||||
|
||||
Core libraries for the Angel Framework.
|
||||
|
|
21
lib/hooks.dart
Normal file
21
lib/hooks.dart
Normal 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);
|
||||
};
|
||||
}
|
|
@ -58,18 +58,18 @@ class AngelHttpException implements Exception {
|
|||
/// Throws a 400 Bad Request error, including an optional arrray of (validation?)
|
||||
/// errors you specify.
|
||||
factory AngelHttpException.badRequest(
|
||||
{String message: '400 Bad Request', List<String> errors: const []}) =>
|
||||
{String message: '400 Bad Request', List<String> errors: const []}) =>
|
||||
new AngelHttpException(null,
|
||||
message: message, errors: errors, statusCode: 400);
|
||||
|
||||
/// Throws a 401 Not Authenticated error.
|
||||
factory AngelHttpException.notAuthenticated(
|
||||
{String message: '401 Not Authenticated'}) =>
|
||||
{String message: '401 Not Authenticated'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 401);
|
||||
|
||||
/// Throws a 402 Payment Required error.
|
||||
factory AngelHttpException.paymentRequired(
|
||||
{String message: '402 Payment Required'}) =>
|
||||
{String message: '402 Payment Required'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 402);
|
||||
|
||||
/// Throws a 403 Forbidden error.
|
||||
|
@ -82,12 +82,12 @@ class AngelHttpException implements Exception {
|
|||
|
||||
/// Throws a 405 Method Not Allowed error.
|
||||
factory AngelHttpException.methodNotAllowed(
|
||||
{String message: '405 Method Not Allowed'}) =>
|
||||
{String message: '405 Method Not Allowed'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 405);
|
||||
|
||||
/// Throws a 406 Not Acceptable error.
|
||||
factory AngelHttpException.notAcceptable(
|
||||
{String message: '406 Not Acceptable'}) =>
|
||||
{String message: '406 Not Acceptable'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 406);
|
||||
|
||||
/// Throws a 408 Timeout error.
|
||||
|
@ -100,83 +100,84 @@ class AngelHttpException implements Exception {
|
|||
|
||||
/// Throws a 422 Not Processable error.
|
||||
factory AngelHttpException.notProcessable(
|
||||
{String message: '422 Not Processable'}) =>
|
||||
{String message: '422 Not Processable'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 422);
|
||||
|
||||
/// Throws a 501 Not Implemented error.
|
||||
factory AngelHttpException.notImplemented(
|
||||
{String message: '501 Not Implemented'}) =>
|
||||
{String message: '501 Not Implemented'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 501);
|
||||
|
||||
/// Throws a 503 Unavailable error.
|
||||
factory AngelHttpException.unavailable({String message: '503 Unavailable'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 503);
|
||||
|
||||
/// Throws a 400 Bad Request error, including an optional arrray of (validation?)
|
||||
/// errors you specify.
|
||||
@Deprecated('Use lowercase constructor instead')
|
||||
/// DEPRECATED: Use lowercase constructor instead.
|
||||
@deprecated
|
||||
factory AngelHttpException.BadRequest(
|
||||
{String message: '400 Bad Request', List<String> errors: const []}) =>
|
||||
new AngelHttpException(null,
|
||||
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(
|
||||
{String message: '401 Not Authenticated'}) =>
|
||||
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(
|
||||
{String message: '402 Payment Required'}) =>
|
||||
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'}) =>
|
||||
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'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 404);
|
||||
|
||||
/// Throws a 405 Method Not Allowed error.
|
||||
@deprecated
|
||||
|
||||
/// DEPRECATED: Use lowercase constructor instead.
|
||||
factory AngelHttpException.MethodNotAllowed(
|
||||
{String message: '405 Method Not Allowed'}) =>
|
||||
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(
|
||||
{String message: '406 Not Acceptable'}) =>
|
||||
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'}) =>
|
||||
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'}) =>
|
||||
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(
|
||||
{String message: '422 Not Processable'}) =>
|
||||
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(
|
||||
{String message: '501 Not Implemented'}) =>
|
||||
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'}) =>
|
||||
new AngelHttpException(null, message: message, statusCode: 503);
|
||||
}
|
||||
|
|
|
@ -176,7 +176,54 @@ class HookedService extends Service {
|
|||
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) {
|
||||
beforeIndexed.listen(listener);
|
||||
beforeRead.listen(listener);
|
||||
|
@ -207,12 +254,12 @@ class HookedService extends Service {
|
|||
Future<List> index([Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeIndexed._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.INDEXED,
|
||||
params: params));
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await beforeIndexed._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.INDEXED,
|
||||
params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -220,7 +267,7 @@ class HookedService extends Service {
|
|||
|
||||
List result = await inner.index(params);
|
||||
HookedServiceEvent after = await afterIndexed._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.INDEXED,
|
||||
params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -230,13 +277,13 @@ class HookedService extends Service {
|
|||
Future read(id, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeRead._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.READ,
|
||||
id: id, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterRead._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.READ,
|
||||
id: id, params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -244,7 +291,7 @@ class HookedService extends Service {
|
|||
|
||||
var result = await inner.read(id, params);
|
||||
HookedServiceEvent after = await afterRead._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.READ,
|
||||
id: id, params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -254,13 +301,13 @@ class HookedService extends Service {
|
|||
Future create(data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeCreated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterCreated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -268,7 +315,7 @@ class HookedService extends Service {
|
|||
|
||||
var result = await inner.create(data, params);
|
||||
HookedServiceEvent after = await afterCreated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -278,13 +325,13 @@ class HookedService extends Service {
|
|||
Future modify(id, data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeModified._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterModified._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -292,7 +339,7 @@ class HookedService extends Service {
|
|||
|
||||
var result = await inner.modify(id, data, params);
|
||||
HookedServiceEvent after = await afterModified._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -302,13 +349,13 @@ class HookedService extends Service {
|
|||
Future update(id, data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeUpdated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterUpdated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -316,7 +363,7 @@ class HookedService extends Service {
|
|||
|
||||
var result = await inner.update(id, data, params);
|
||||
HookedServiceEvent after = await afterUpdated._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -326,13 +373,13 @@ class HookedService extends Service {
|
|||
Future remove(id, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeRemoved._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterRemoved._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params, result: before.result));
|
||||
return after.result;
|
||||
|
@ -340,7 +387,7 @@ class HookedService extends Service {
|
|||
|
||||
var result = await inner.remove(id, params);
|
||||
HookedServiceEvent after = await afterRemoved._emit(
|
||||
new HookedServiceEvent._base(_getRequest(_params),
|
||||
new HookedServiceEvent._base(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params, result: result));
|
||||
return after.result;
|
||||
|
@ -375,7 +422,7 @@ class HookedService extends Service {
|
|||
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);
|
||||
return await dispatcher._emit(ev);
|
||||
}
|
||||
|
@ -399,6 +446,7 @@ class HookedServiceEvent {
|
|||
bool _canceled = false;
|
||||
String _eventName;
|
||||
var _id;
|
||||
bool _isAfter;
|
||||
var data;
|
||||
Map _params;
|
||||
var _result;
|
||||
|
@ -409,6 +457,10 @@ class HookedServiceEvent {
|
|||
|
||||
get id => _id;
|
||||
|
||||
bool get isAfter => _isAfter == true;
|
||||
|
||||
bool get isBefore => !isAfter;
|
||||
|
||||
Map get params => _params;
|
||||
|
||||
RequestContext get request => _request;
|
||||
|
@ -420,8 +472,8 @@ class HookedServiceEvent {
|
|||
/// The inner service whose method was hooked.
|
||||
Service service;
|
||||
|
||||
HookedServiceEvent._base(this._request, this._response, Service this.service,
|
||||
String this._eventName,
|
||||
HookedServiceEvent._base(this._isAfter, this._request, this._response,
|
||||
Service this.service, String this._eventName,
|
||||
{id, this.data, Map params, result}) {
|
||||
_id = id;
|
||||
_params = params ?? {};
|
||||
|
|
|
@ -40,32 +40,32 @@ class Service extends Routable {
|
|||
|
||||
/// Retrieves all resources.
|
||||
Future<List> index([Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Retrieves the desired resource.
|
||||
Future read(id, [Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Creates a resource.
|
||||
Future create(data, [Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Modifies a resource.
|
||||
Future modify(id, data, [Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Overwrites a resource.
|
||||
Future update(id, data, [Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Removes the given resource.
|
||||
Future remove(id, [Map params]) {
|
||||
throw new AngelHttpException.MethodNotAllowed();
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
void addRoutes() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_framework
|
||||
version: 1.0.0-dev.50
|
||||
version: 1.0.0-dev.51
|
||||
description: Core libraries for the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
|
|
Loading…
Reference in a new issue