48
This commit is contained in:
parent
eb1e931b89
commit
929e7bbac6
8 changed files with 219 additions and 62 deletions
|
@ -1,6 +1,6 @@
|
|||
# angel_framework
|
||||
|
||||
[![pub 1.0.0-dev.47](https://img.shields.io/badge/pub-1.0.0--dev.47-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||
[![pub 1.0.0-dev.48](https://img.shields.io/badge/pub-1.0.0--dev.48-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.
|
||||
|
|
|
@ -17,11 +17,14 @@ import 'server.dart' show Angel, preInject;
|
|||
/// Regular request handlers can also skip DI entirely, lowering response time
|
||||
/// and memory use.
|
||||
class InjectionRequest {
|
||||
/// A list of the data required for a DI-enabled method to run.
|
||||
/// Optional, typed data that can be passed to a DI-enabled method.
|
||||
Map<String, Type> named = {};
|
||||
|
||||
/// A list of the arguments required for a DI-enabled method to run.
|
||||
final List required = [];
|
||||
|
||||
/// A list of the data that can be null in a DI-enabled method.
|
||||
final List optional = [];
|
||||
/// A list of the arguments that can be null in a DI-enabled method.
|
||||
final List<String> optional = [];
|
||||
}
|
||||
|
||||
/// Supports grouping routes with shared functionality.
|
||||
|
@ -121,7 +124,7 @@ class Controller {
|
|||
}
|
||||
|
||||
/// Shortcut for calling [preInject], and then [handleContained].
|
||||
///
|
||||
///
|
||||
/// Use this to instantly create a request handler for a DI-enabled method.
|
||||
RequestHandler createDynamicHandler(handler,
|
||||
{Iterable<String> optional: const []}) {
|
||||
|
@ -173,8 +176,27 @@ RequestHandler handleContained(handler, InjectionRequest injection) {
|
|||
}
|
||||
}
|
||||
|
||||
Map<Symbol, dynamic> named = {};
|
||||
injection.required.forEach(inject);
|
||||
var result = Function.apply(handler, args);
|
||||
|
||||
injection.named.forEach((k, v) {
|
||||
var name = new Symbol(k);
|
||||
if (req.params.containsKey(k))
|
||||
named[name] = v;
|
||||
else if (req.injections.containsKey(k))
|
||||
named[name] = v;
|
||||
else if (req.injections.containsKey(v) && v != dynamic)
|
||||
named[name] = v;
|
||||
else {
|
||||
try {
|
||||
named[name] = req.app.container.make(v);
|
||||
} catch (e) {
|
||||
named[name] = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var result = Function.apply(handler, args, named);
|
||||
return result is Future ? await result : result;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ library angel_framework.http;
|
|||
import 'dart:async';
|
||||
import 'package:merge_map/merge_map.dart';
|
||||
import '../util.dart';
|
||||
import 'request_context.dart';
|
||||
import 'response_context.dart';
|
||||
import 'metadata.dart';
|
||||
import 'service.dart';
|
||||
|
||||
|
@ -39,6 +41,14 @@ class HookedService extends Service {
|
|||
if (inner.app != null) this.app = inner.app;
|
||||
}
|
||||
|
||||
Map _stripReq(Map params) {
|
||||
if (params == null)
|
||||
return params;
|
||||
else
|
||||
return params..remove('__requestctx')..remove('__responsectx');
|
||||
}
|
||||
|
||||
/// Adds hooks to this instance.
|
||||
void addHooks() {
|
||||
Hooks hooks = getAnnotation(inner, Hooks);
|
||||
final before = [];
|
||||
|
@ -74,6 +84,7 @@ class HookedService extends Service {
|
|||
applyListeners(inner.removed, afterRemoved, true);
|
||||
}
|
||||
|
||||
/// Adds routes to this instance.
|
||||
@override
|
||||
void addRoutes() {
|
||||
// Set up our routes. We still need to copy middleware from inner service
|
||||
|
@ -87,7 +98,11 @@ class HookedService extends Service {
|
|||
|
||||
Middleware indexMiddleware = getAnnotation(inner.index, Middleware);
|
||||
get('/', (req, res) async {
|
||||
return await this.index(mergeMap([req.query, restProvider]));
|
||||
return await this.index(mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
]));
|
||||
},
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
|
@ -96,8 +111,13 @@ class HookedService extends Service {
|
|||
Middleware createMiddleware = getAnnotation(inner.create, Middleware);
|
||||
post(
|
||||
'/',
|
||||
(req, res) async =>
|
||||
await this.create(req.body, mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.create(
|
||||
req.body,
|
||||
mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -107,8 +127,13 @@ class HookedService extends Service {
|
|||
|
||||
get(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.read(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.read(
|
||||
req.params['id'],
|
||||
mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll((readMiddleware == null) ? [] : readMiddleware.handlers));
|
||||
|
@ -117,7 +142,13 @@ class HookedService extends Service {
|
|||
patch(
|
||||
'/:id',
|
||||
(req, res) async => await this.modify(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
req.params['id'],
|
||||
req.body,
|
||||
mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -127,7 +158,13 @@ class HookedService extends Service {
|
|||
post(
|
||||
'/:id',
|
||||
(req, res) async => await this.update(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
req.params['id'],
|
||||
req.body,
|
||||
mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -136,8 +173,13 @@ class HookedService extends Service {
|
|||
Middleware removeMiddleware = getAnnotation(inner.remove, Middleware);
|
||||
delete(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.remove(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.remove(
|
||||
req.params['id'],
|
||||
mergeMap([
|
||||
req.query,
|
||||
restProvider,
|
||||
{'__requestctx': req, '__responsectx': res}
|
||||
])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -147,123 +189,180 @@ class HookedService extends Service {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List> index([Map params]) async {
|
||||
Future<List> index([Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeIndexed._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.INDEXED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.INDEXED,
|
||||
params: params));
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await beforeIndexed._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.INDEXED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.INDEXED,
|
||||
params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
List result = await inner.index(params);
|
||||
HookedServiceEvent after = await afterIndexed._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.INDEXED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.INDEXED,
|
||||
params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future read(id, [Map params]) async {
|
||||
Future read(id, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeRead._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.READ,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.READ,
|
||||
id: id, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterRead._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.READ,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.READ,
|
||||
id: id, params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
var result = await inner.read(id, params);
|
||||
HookedServiceEvent after = await afterRead._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.READ,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.READ,
|
||||
id: id, params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future create(data, [Map params]) async {
|
||||
Future create(data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeCreated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.CREATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterCreated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.CREATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
var result = await inner.create(data, params);
|
||||
HookedServiceEvent after = await afterCreated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.CREATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.CREATED,
|
||||
data: data, params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future modify(id, data, [Map params]) async {
|
||||
Future modify(id, data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeModified._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.MODIFIED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterModified._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.MODIFIED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
var result = await inner.modify(id, data, params);
|
||||
HookedServiceEvent after = await afterModified._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.MODIFIED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.MODIFIED,
|
||||
id: id, data: data, params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future update(id, data, [Map params]) async {
|
||||
Future update(id, data, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeUpdated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.UPDATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterUpdated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.UPDATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
var result = await inner.update(id, data, params);
|
||||
HookedServiceEvent after = await afterUpdated._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.UPDATED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.UPDATED,
|
||||
id: id, data: data, params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future remove(id, [Map params]) async {
|
||||
Future remove(id, [Map _params]) async {
|
||||
var params = _stripReq(_params);
|
||||
HookedServiceEvent before = await beforeRemoved._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.REMOVED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params));
|
||||
|
||||
if (before._canceled) {
|
||||
HookedServiceEvent after = await afterRemoved._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.REMOVED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params, result: before.result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
var result = await inner.remove(id, params);
|
||||
HookedServiceEvent after = await afterRemoved._emit(
|
||||
new HookedServiceEvent._base(inner, HookedServiceEvent.REMOVED,
|
||||
new HookedServiceEvent._base(_params['__requestctx'],
|
||||
params['__responsectx'], inner, HookedServiceEvent.REMOVED,
|
||||
id: id, params: params, result: result));
|
||||
return after.result;
|
||||
}
|
||||
|
||||
/// Fires an `after` event. This will not be propagated to clients,
|
||||
/// but will be broadcasted to WebSockets, etc.
|
||||
Future<HookedServiceEvent> fire(String eventName, result, [HookedServiceEventListener callback]) async {
|
||||
HookedServiceEventDispatcher dispatcher;
|
||||
|
||||
switch (eventName) {
|
||||
case HookedServiceEvent.INDEXED:
|
||||
dispatcher = afterIndexed;
|
||||
break;
|
||||
case HookedServiceEvent.READ:
|
||||
dispatcher = afterRead;
|
||||
break;
|
||||
case HookedServiceEvent.CREATED:
|
||||
dispatcher = afterCreated;
|
||||
break;
|
||||
case HookedServiceEvent.MODIFIED:
|
||||
dispatcher = afterModified;
|
||||
break;
|
||||
case HookedServiceEvent.UPDATED:
|
||||
dispatcher = afterUpdated;
|
||||
break;
|
||||
case HookedServiceEvent.REMOVED:
|
||||
dispatcher = afterRemoved;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentError("Invalid service event name: '$eventName'");
|
||||
}
|
||||
|
||||
var ev = new HookedServiceEvent._base(null, null, this, eventName);
|
||||
if (callback != null) await callback(ev);
|
||||
return await dispatcher._emit(ev);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fired when a hooked service is invoked.
|
||||
|
@ -287,6 +386,8 @@ class HookedServiceEvent {
|
|||
var data;
|
||||
Map _params;
|
||||
var _result;
|
||||
RequestContext _request;
|
||||
ResponseContext _response;
|
||||
|
||||
String get eventName => _eventName;
|
||||
|
||||
|
@ -294,12 +395,17 @@ class HookedServiceEvent {
|
|||
|
||||
Map get params => _params;
|
||||
|
||||
RequestContext get request => _request;
|
||||
|
||||
ResponseContext get response => _response;
|
||||
|
||||
get result => _result;
|
||||
|
||||
/// The inner service whose method was hooked.
|
||||
Service service;
|
||||
|
||||
HookedServiceEvent._base(Service this.service, String this._eventName,
|
||||
HookedServiceEvent._base(this._result, this._response, Service this.service,
|
||||
String this._eventName,
|
||||
{id, this.data, Map params, result}) {
|
||||
_id = id;
|
||||
_params = params ?? {};
|
||||
|
@ -308,7 +414,7 @@ class HookedServiceEvent {
|
|||
}
|
||||
|
||||
/// Triggered on a hooked service event.
|
||||
typedef Future HookedServiceEventListener(HookedServiceEvent event);
|
||||
typedef HookedServiceEventListener(HookedServiceEvent event);
|
||||
|
||||
/// Can be listened to, but events may be canceled.
|
||||
class HookedServiceEventDispatcher {
|
||||
|
|
|
@ -97,6 +97,24 @@ class RequestContext extends Extensible {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
/// Grabs an object by key or type from [params], [injections], or
|
||||
/// [app].container. Use this to perform dependency injection
|
||||
/// within a service hook.
|
||||
grab(key) {
|
||||
if (params.containsKey(key))
|
||||
return params[key];
|
||||
else if (injections.containsKey(key))
|
||||
return injections[key];
|
||||
else if (key is Type) {
|
||||
try {
|
||||
return app.container.make(key);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
void inject(type, value) {
|
||||
injections[type] = value;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,6 @@ class ResponseContext extends Extensible {
|
|||
}
|
||||
|
||||
/// Serializes JSON to the response.
|
||||
@Deprecated('Please use `serialize` instead.')
|
||||
void json(value) => serialize(value, contentType: ContentType.JSON);
|
||||
|
||||
/// Returns a JSONP response.
|
||||
|
@ -232,8 +231,7 @@ class ResponseContext extends Extensible {
|
|||
void serialize(value, {contentType}) {
|
||||
var text = serializer(value);
|
||||
write(text);
|
||||
headers[HttpHeaders.CONTENT_LENGTH] = text.length.toString();
|
||||
|
||||
|
||||
if (contentType is String)
|
||||
headers[HttpHeaders.CONTENT_TYPE] = contentType;
|
||||
else if (contentType is ContentType) this.contentType = contentType;
|
||||
|
|
|
@ -132,12 +132,11 @@ class Angel extends AngelBase {
|
|||
|
||||
/// Loads some base dependencies into the service container.
|
||||
void bootstrapContainer() {
|
||||
if (runtimeType != Angel) container.singleton(this, as: Angel);
|
||||
container.singleton(this, as: AngelBase);
|
||||
container.singleton(this, as: Routable);
|
||||
container.singleton(this, as: Router);
|
||||
container.singleton(this);
|
||||
|
||||
if (runtimeType != Angel) container.singleton(this, as: Angel);
|
||||
}
|
||||
|
||||
Future<bool> executeHandler(
|
||||
|
@ -189,6 +188,7 @@ class Angel extends AngelBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Handles a single request.
|
||||
Future handleRequest(HttpRequest request) async {
|
||||
try {
|
||||
_beforeProcessed.add(request);
|
||||
|
@ -270,11 +270,12 @@ class Angel extends AngelBase {
|
|||
}
|
||||
|
||||
for (var key in res.headers.keys) {
|
||||
request.response.headers.set(key, res.headers[key]);
|
||||
request.response.headers.add(key, res.headers[key]);
|
||||
}
|
||||
|
||||
request.response.headers.chunkedTransferEncoding =
|
||||
res.chunked ?? true;
|
||||
request.response.headers
|
||||
..chunkedTransferEncoding = res.chunked ?? true
|
||||
..set(HttpHeaders.CONTENT_LENGTH, res.buffer.length);
|
||||
|
||||
request.response
|
||||
..statusCode = res.statusCode
|
||||
|
@ -417,17 +418,23 @@ class Angel extends AngelBase {
|
|||
_errorHandler = handler;
|
||||
}
|
||||
|
||||
Angel({bool debug: false}) : super(debug: debug) {
|
||||
/// Default constructor. ;)
|
||||
Angel({bool debug: false}) : super(debug: debug == true) {
|
||||
bootstrapContainer();
|
||||
}
|
||||
|
||||
/// An instance mounted on a server started by the [serverGenerator].
|
||||
factory Angel.custom(ServerGenerator serverGenerator, {bool debug: false}) =>
|
||||
new Angel(debug: debug == true).._serverGenerator = serverGenerator;
|
||||
|
||||
/// Creates an HTTPS server.
|
||||
///
|
||||
/// Provide paths to a certificate chain and server key (both .pem).
|
||||
/// If no password is provided, a random one will be generated upon running
|
||||
/// the server.
|
||||
factory Angel.secure(String certificateChainPath, String serverKeyPath,
|
||||
{bool debug: false, String password}) {
|
||||
final app = new Angel(debug: debug);
|
||||
final app = new Angel(debug: debug == true);
|
||||
|
||||
app._serverGenerator = (InternetAddress address, int port) async {
|
||||
var certificateChain =
|
||||
|
@ -455,16 +462,22 @@ InjectionRequest preInject(Function handler) {
|
|||
var name = MirrorSystem.getName(parameter.simpleName);
|
||||
var type = parameter.type.reflectedType;
|
||||
|
||||
if (type == RequestContext || type == ResponseContext) {
|
||||
injection.required.add(type);
|
||||
} else if (name == 'req') {
|
||||
injection.required.add(RequestContext);
|
||||
} else if (name == 'res') {
|
||||
injection.required.add(ResponseContext);
|
||||
} else if (type == dynamic) {
|
||||
injection.required.add(name);
|
||||
if (!parameter.isNamed) {
|
||||
if (parameter.isOptional) injection.optional.add(name);
|
||||
|
||||
if (type == RequestContext || type == ResponseContext) {
|
||||
injection.required.add(type);
|
||||
} else if (name == 'req') {
|
||||
injection.required.add(RequestContext);
|
||||
} else if (name == 'res') {
|
||||
injection.required.add(ResponseContext);
|
||||
} else if (type == dynamic) {
|
||||
injection.required.add(name);
|
||||
} else {
|
||||
injection.required.add([name, type]);
|
||||
}
|
||||
} else {
|
||||
injection.required.add([name, type]);
|
||||
injection.named[name] = type;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_framework
|
||||
version: 1.0.0-dev.47
|
||||
version: 1.0.0-dev.48
|
||||
description: Core libraries for the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
|
|
|
@ -24,7 +24,7 @@ main() {
|
|||
|
||||
app.get("/errands", (Todo singleton) => singleton);
|
||||
app.get("/errands3",
|
||||
(Errand singleton, Todo foo, RequestContext req) => singleton.text);
|
||||
({Errand singleton, Todo foo, RequestContext req}) => singleton.text);
|
||||
await app.configure(new SingletonController());
|
||||
await app.configure(new ErrandController());
|
||||
|
||||
|
|
Loading…
Reference in a new issue