optional expose
This commit is contained in:
parent
91bc517b1f
commit
0a9b5c118f
4 changed files with 72 additions and 8 deletions
|
@ -1,4 +1,5 @@
|
|||
# 2.0.5
|
||||
* Make `@Expose()` in `Controller` optional. https://github.com/angel-dart/angel/issues/107
|
||||
* Add `allowHttp1` to `AngelHttp2` constructors. https://github.com/angel-dart/angel/issues/108
|
||||
* Add `deserializeBody` and `decodeBody` to `RequestContext`. https://github.com/angel-dart/angel/issues/109
|
||||
* Add `HostnameRouter`, which allows for routing based on hostname. https://github.com/angel-dart/angel/issues/110
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:async';
|
|||
import 'package:angel_container/angel_container.dart';
|
||||
import 'package:angel_route/angel_route.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import 'package:recase/recase.dart';
|
||||
import '../core/core.dart';
|
||||
|
||||
/// Supports grouping routes with shared functionality.
|
||||
|
@ -86,7 +86,15 @@ class Controller {
|
|||
.map((m) => m.reflectee)
|
||||
.firstWhere((r) => r is Expose, orElse: () => null) as Expose;
|
||||
|
||||
if (exposeDecl == null) return;
|
||||
if (exposeDecl == null) {
|
||||
// If this has a @noExpose, return null.
|
||||
if (decl.function.annotations.any((m) => m.reflectee is NoExpose)) {
|
||||
return;
|
||||
} else {
|
||||
// Otherwise, create an @Expose.
|
||||
exposeDecl = Expose(null);
|
||||
}
|
||||
}
|
||||
|
||||
var reflectedMethod =
|
||||
instanceMirror.getField(methodName).reflectee as Function;
|
||||
|
@ -117,6 +125,30 @@ class Controller {
|
|||
injection.optional?.addAll(exposeDecl.allowNull);
|
||||
}
|
||||
|
||||
// If there is no path, reverse-engineer one.
|
||||
var path = exposeDecl.path;
|
||||
if (path == null) {
|
||||
var parts = <String>[];
|
||||
parts.add(ReCase(method.name).snakeCase.replaceAll(_multiScore, '_'));
|
||||
|
||||
// Try to infer String, int, or double.
|
||||
for (var p in injection.required) {
|
||||
if (p is List && p.length == 2 && p[0] is String && p[1] is Type) {
|
||||
var name = p[0] as String;
|
||||
var type = p[1] as Type;
|
||||
if (type == String) {
|
||||
parts.add(':$name');
|
||||
} else if (type == int) {
|
||||
parts.add('int:$name');
|
||||
} else if (type == double) {
|
||||
parts.add('double:$name');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path = parts.join('/');
|
||||
}
|
||||
|
||||
routeMappings[name] = routable.addRoute(exposeDecl.method,
|
||||
exposeDecl.path, handleContained(reflectedMethod, injection),
|
||||
middleware: middleware);
|
||||
|
@ -127,10 +159,22 @@ class Controller {
|
|||
/// Used to add additional routes to the router from within a [Controller].
|
||||
void configureRoutes(Routable routable) {}
|
||||
|
||||
static final RegExp _multiScore = RegExp(r'__+');
|
||||
|
||||
/// Finds the [Expose] declaration for this class.
|
||||
Expose findExpose(Reflector reflector) => reflector
|
||||
Expose findExpose(Reflector reflector, {bool concreteOnly = false}) {
|
||||
var existing = reflector
|
||||
.reflectClass(runtimeType)
|
||||
.annotations
|
||||
.map((m) => m.reflectee)
|
||||
.firstWhere((r) => r is Expose, orElse: () => null) as Expose;
|
||||
return existing ??
|
||||
(concreteOnly
|
||||
? null
|
||||
: Expose(ReCase(runtimeType.toString())
|
||||
.snakeCase
|
||||
.replaceAll('_controller', '')
|
||||
.replaceAll('_ctrl', '')
|
||||
.replaceAll(_multiScore, '_')));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,14 @@ class Hooks {
|
|||
const Hooks({this.before = const [], this.after = const []});
|
||||
}
|
||||
|
||||
/// Exposes a [Controller] to the Internet.
|
||||
/// Specifies to NOT expose a method to the Internet.
|
||||
class NoExpose {
|
||||
const NoExpose();
|
||||
}
|
||||
|
||||
const NoExpose noExpose = NoExpose();
|
||||
|
||||
/// Exposes a [Controller] or method to the Internet.
|
||||
class Expose {
|
||||
final String method;
|
||||
final String path;
|
||||
|
@ -29,11 +36,22 @@ class Expose {
|
|||
final String as;
|
||||
final List<String> allowNull;
|
||||
|
||||
static const Expose get = Expose(null, method: 'GET'),
|
||||
post = Expose(null, method: 'POST'),
|
||||
patch = Expose(null, method: 'PATCH'),
|
||||
put = Expose(null, method: 'PUT'),
|
||||
delete = Expose(null, method: 'DELETE'),
|
||||
head = Expose(null, method: 'HEAD');
|
||||
|
||||
const Expose(this.path,
|
||||
{this.method = "GET",
|
||||
this.middleware = const [],
|
||||
this.as,
|
||||
this.allowNull = const []});
|
||||
|
||||
const Expose.method(this.method,
|
||||
{this.middleware, this.as, this.allowNull = const []})
|
||||
: path = null;
|
||||
}
|
||||
|
||||
/// Used to apply special dependency injections or functionality to a function parameter.
|
||||
|
|
|
@ -25,6 +25,7 @@ dependencies:
|
|||
path: ^1.0.0
|
||||
pedantic: ^1.0.0
|
||||
quiver_hashcode: ^2.0.0
|
||||
recase: ^2.0.0
|
||||
stack_trace: ^1.0.0
|
||||
tuple: ^1.0.0
|
||||
uuid: ^2.0.0-rc.1
|
||||
|
|
Loading…
Reference in a new issue