Merge branch 'master' into experimental

This commit is contained in:
Tobe O 2019-10-12 10:04:13 -04:00
commit 564310baca
6 changed files with 36 additions and 10 deletions

View file

@ -6,6 +6,10 @@
* Default to using `ThrowingReflector`, instead of `EmptyReflector`. This will give a more descriptive * Default to using `ThrowingReflector`, instead of `EmptyReflector`. This will give a more descriptive
error when trying to use controllers, etc. without reflection enabled. error when trying to use controllers, etc. without reflection enabled.
# 2.0.4+1
* Run `Controller.configureRoutes` before mounting `@Expose` routes.
* Make `Controller.configureServer` always return a `Future`.
# 2.0.4 # 2.0.4
* Prepare for Dart SDK change to `Stream<List<int>>` that are now * Prepare for Dart SDK change to `Stream<List<int>>` that are now
`Stream<Uint8List>`. `Stream<Uint8List>`.

View file

@ -27,7 +27,7 @@ class Controller {
/// Applies routes, DI, and other configuration to an [app]. /// Applies routes, DI, and other configuration to an [app].
@mustCallSuper @mustCallSuper
FutureOr<void> configureServer(Angel app) { Future<void> configureServer(Angel app) async {
_app = app; _app = app;
if (injectSingleton != false) { if (injectSingleton != false) {
@ -36,13 +36,13 @@ class Controller {
} }
} }
var name = applyRoutes(app, app.container.reflector); var name = await applyRoutes(app, app.container.reflector);
app.controllers[name] = this; app.controllers[name] = this;
return null; return null;
} }
/// Applies the routes from this [Controller] to some [router]. /// Applies the routes from this [Controller] to some [router].
String applyRoutes(Router router, Reflector reflector) { Future<String> applyRoutes(Router router, Reflector reflector) async {
// Load global expose decl // Load global expose decl
var classMirror = reflector.reflectClass(this.runtimeType); var classMirror = reflector.reflectClass(this.runtimeType);
Expose exposeDecl = findExpose(reflector); Expose exposeDecl = findExpose(reflector);
@ -62,8 +62,8 @@ class Controller {
..addAll(middleware); ..addAll(middleware);
final routeBuilder = final routeBuilder =
_routeBuilder(reflector, instanceMirror, routable, handlers); _routeBuilder(reflector, instanceMirror, routable, handlers);
await configureRoutes(routable);
classMirror.declarations.forEach(routeBuilder); classMirror.declarations.forEach(routeBuilder);
configureRoutes(routable);
// Return the name. // Return the name.
return exposeDecl.as?.isNotEmpty == true ? exposeDecl.as : typeMirror.name; return exposeDecl.as?.isNotEmpty == true ? exposeDecl.as : typeMirror.name;
@ -178,8 +178,16 @@ class Controller {
}; };
} }
/// Used to add additional routes to the router from within a [Controller]. /// Used to add additional routes or middlewares to the router from within
void configureRoutes(Routable routable) {} /// a [Controller].
///
/// ```dart
/// @override
/// FutureOr<void> configureRoutes(Routable routable) {
/// routable.all('*', myMiddleware);
/// }
/// ```
FutureOr<void> configureRoutes(Routable routable) {}
static final RegExp _methods = RegExp(r'^(get|post|patch|delete)'); static final RegExp _methods = RegExp(r'^(get|post|patch|delete)');
static final RegExp _multiScore = RegExp(r'__+'); static final RegExp _multiScore = RegExp(r'__+');

View file

@ -28,7 +28,21 @@ class NoExpose {
const NoExpose noExpose = NoExpose(); const NoExpose noExpose = NoExpose();
/// Exposes a [Controller] or method to the Internet. /// Exposes a [Controller] or a [Controller] method to the Internet.
/// Example:
///
/// ```dart
/// @Expose('/elements')
/// class ElementController extends Controller {
///
/// @Expose('/')
/// List<Element> getList() => someComputationHere();
///
/// @Expose('/int:elementId')
/// getElement(int elementId) => someOtherComputation();
///
/// }
/// ```
class Expose { class Expose {
final String method; final String method;
final String path; final String path;

View file

@ -61,7 +61,7 @@ abstract class ResponseContext<RawResponse>
/// Serializes response data into a String. /// Serializes response data into a String.
/// ///
/// The default is conversion into JSON via `package:json_god`. /// The default is conversion into JSON via `json.encode`.
/// ///
/// If you are 100% sure that your response handlers will only /// If you are 100% sure that your response handlers will only
/// be JSON-encodable objects (i.e. primitives, `List`s and `Map`s), /// be JSON-encodable objects (i.e. primitives, `List`s and `Map`s),

View file

@ -113,7 +113,7 @@ main() {
}, optional: ['bar'])); }, optional: ['bar']));
var rq = MockHttpRequest('GET', Uri(path: 'foo')); var rq = MockHttpRequest('GET', Uri(path: 'foo'));
await AngelHttp(app).handleRequest(rq); await AngelHttp(app).handleRequest(rq);
var body = await rq.response.transform(utf8.decoder).join(); var body = await utf8.decoder.bind(rq.response).join();
expect(json.decode(body), 2); expect(json.decode(body), 2);
}); });

View file

@ -28,7 +28,7 @@ main() {
app.container.registerSingleton(Todo(text: TEXT, over: OVER)); app.container.registerSingleton(Todo(text: TEXT, over: OVER));
app.container.registerFactory<Future<Foo>>((container) async { app.container.registerFactory<Future<Foo>>((container) async {
var req = container.make<RequestContext>(); var req = container.make<RequestContext>();
var text = await req.body.transform(utf8.decoder).join(); var text = await utf8.decoder.bind(req.body).join();
return Foo(text); return Foo(text);
}); });