Merge branch 'feature/refactor_framework' into release/5.0.0

This commit is contained in:
thomashii 2022-02-15 08:48:48 +08:00
commit 8469a05ff0
24 changed files with 138 additions and 98 deletions

View file

@ -6,8 +6,8 @@ publish_to: none
environment: environment:
sdk: ">=2.10.0 <3.0.0" sdk: ">=2.10.0 <3.0.0"
dependencies: dependencies:
angel_auth: angel_auth: ^2.0.0
angel_framework: angel_framework: ^2.0.0
http: ^0.13.0 http: ^0.13.0
path: ^1.0.0 path: ^1.0.0
twitter: twitter:

View file

@ -3,6 +3,10 @@
## 6.0.0 ## 6.0.0
* Updated to min SDK 2.15.x * Updated to min SDK 2.15.x
* Updated `container` to non nullable
* Updated `angel` to non nullable
* Updated `logger` to non nullable
* Refactored error handler
## 5.0.0 ## 5.0.0

View file

@ -12,7 +12,13 @@ class Controller {
Angel? _app; Angel? _app;
/// The [Angel] application powering this controller. /// The [Angel] application powering this controller.
Angel? get app => _app; Angel get app {
if (_app == null) {
throw ArgumentError("Angel is not instantiated.");
}
return _app!;
}
/// If `true` (default), this class will inject itself as a singleton into the [app]'s container when bootstrapped. /// If `true` (default), this class will inject itself as a singleton into the [app]'s container when bootstrapped.
final bool injectSingleton; final bool injectSingleton;
@ -36,12 +42,12 @@ class Controller {
_app = app; _app = app;
if (injectSingleton != false) { if (injectSingleton != false) {
if (!app.container!.has(runtimeType)) { if (!app.container.has(runtimeType)) {
_app!.container!.registerSingleton(this, as: runtimeType); _app!.container.registerSingleton(this, as: runtimeType);
} }
} }
var name = await 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;
} }

View file

@ -45,7 +45,9 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
HookedService(this.inner) { HookedService(this.inner) {
// Clone app instance // Clone app instance
if (inner.app != null) app = inner.app; if (inner.isAppActive) {
app = inner.app;
}
} }
@override @override
@ -62,9 +64,9 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
return params['__responsectx'] as ResponseContext?; return params['__responsectx'] as ResponseContext?;
} }
Map<String, dynamic>? _stripReq(Map<String, dynamic>? params) { Map<String, dynamic> _stripReq(Map<String, dynamic>? params) {
if (params == null) { if (params == null) {
return params; return {};
} else { } else {
return params.keys return params.keys
.where((key) => key != '__requestctx' && key != '__responsectx') .where((key) => key != '__requestctx' && key != '__responsectx')
@ -97,7 +99,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
/// Adds hooks to this instance. /// Adds hooks to this instance.
void addHooks(Angel app) { void addHooks(Angel app) {
var hooks = getAnnotation<Hooks>(inner, app.container!.reflector); var hooks = getAnnotation<Hooks>(inner, app.container.reflector);
var before = <HookedServiceEventListener<Id, Data, T>>[]; var before = <HookedServiceEventListener<Id, Data, T>>[];
var after = <HookedServiceEventListener<Id, Data, T>>[]; var after = <HookedServiceEventListener<Id, Data, T>>[];
@ -109,7 +111,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
void applyListeners( void applyListeners(
Function fn, HookedServiceEventDispatcher<Id, Data, T> dispatcher, Function fn, HookedServiceEventDispatcher<Id, Data, T> dispatcher,
[bool? isAfter]) { [bool? isAfter]) {
var hooks = getAnnotation<Hooks>(fn, app.container!.reflector); var hooks = getAnnotation<Hooks>(fn, app.container.reflector);
final listeners = <HookedServiceEventListener<Id, Data, T>>[ final listeners = <HookedServiceEventListener<Id, Data, T>>[
...isAfter == true ? after : before ...isAfter == true ? after : before
]; ];
@ -512,7 +514,7 @@ class HookedServiceEvent<Id, Data, T extends Service<Id, Data>> {
/// Resolves a service from the application. /// Resolves a service from the application.
/// ///
/// Shorthand for `e.service.app.service(...)`. /// Shorthand for `e.service.app.service(...)`.
Service? getService(Pattern path) => service.app!.findService(path); Service? getService(Pattern path) => service.app.findService(path);
bool _canceled = false; bool _canceled = false;
final String _eventName; final String _eventName;
@ -532,7 +534,7 @@ class HookedServiceEvent<Id, Data, T extends Service<Id, Data>> {
bool get isBefore => !isAfter; bool get isBefore => !isAfter;
Map? get params => _params; Map get params => _params ?? {};
RequestContext? get request => _request; RequestContext? get request => _request;

View file

@ -12,7 +12,7 @@ RequestHandler ioc(Function handler, {Iterable<String> optional = const []}) {
RequestHandler? contained; RequestHandler? contained;
if (req.app?.container != null) { if (req.app?.container != null) {
var injection = preInject(handler, req.app!.container!.reflector); var injection = preInject(handler, req.app!.container.reflector);
//if (injection != null) { //if (injection != null) {
injection.optional.addAll(optional); injection.optional.addAll(optional);
contained = handleContained(handler, injection); contained = handleContained(handler, injection);
@ -70,7 +70,7 @@ Future resolveInjection(requirement, InjectionRequest injection,
} }
} else if (requirement is Type && requirement != dynamic) { } else if (requirement is Type && requirement != dynamic) {
try { try {
var futureType = container!.reflector.reflectFutureOf(requirement); var futureType = container.reflector.reflectFutureOf(requirement);
if (container.has(futureType.reflectedType)) { if (container.has(futureType.reflectedType)) {
return await container.make(futureType.reflectedType); return await container.make(futureType.reflectedType);
} }
@ -78,7 +78,7 @@ Future resolveInjection(requirement, InjectionRequest injection,
// Ignore. // Ignore.
} }
return await container!.make(requirement); return await container.make(requirement);
} else if (throwOnUnresolved) { } else if (throwOnUnresolved) {
throw ArgumentError( throw ArgumentError(
'$requirement cannot be injected into a request handler.'); '$requirement cannot be injected into a request handler.');

View file

@ -287,7 +287,7 @@ abstract class ResponseContext<RawResponse>
} }
final head = controller final head = controller
.findExpose(app!.container!.reflector)! .findExpose(app!.container.reflector)!
.path .path
.toString() .toString()
.replaceAll(_straySlashes, ''); .replaceAll(_straySlashes, '');

View file

@ -48,14 +48,15 @@ class Routable extends Router<RequestHandler> {
final Map<Pattern, Service?> _serviceLookups = {}; final Map<Pattern, Service?> _serviceLookups = {};
final Map configuration = {}; final Map configuration = {};
final Container? _container; final Container _container;
Routable([Reflector? reflector]) Routable([Reflector? reflector])
: _container = reflector == null ? null : Container(reflector), // : _container = reflector == null ? null : Container(reflector),
: _container = Container(reflector ?? ThrowingReflector()),
super(); super();
/// A [Container] used to inject dependencies. /// A [Container] used to inject dependencies.
Container? get container => _container; Container get container => _container;
void close() { void close() {
_services.clear(); _services.clear();
@ -99,10 +100,10 @@ class Routable extends Router<RequestHandler> {
{Iterable<RequestHandler> middleware = const {}}) { {Iterable<RequestHandler> middleware = const {}}) {
final handlers = <RequestHandler>[]; final handlers = <RequestHandler>[];
// Merge @Middleware declaration, if any // Merge @Middleware declaration, if any
var reflector = _container?.reflector; var reflector = _container.reflector;
if (reflector != null && reflector is! ThrowingReflector) { if (reflector is! ThrowingReflector) {
var middlewareDeclaration = var middlewareDeclaration =
getAnnotation<Middleware>(handler, _container?.reflector); getAnnotation<Middleware>(handler, _container.reflector);
if (middlewareDeclaration != null) { if (middlewareDeclaration != null) {
handlers.addAll(middlewareDeclaration.handlers); handlers.addAll(middlewareDeclaration.handlers);
} }

View file

@ -4,6 +4,7 @@ import 'dart:async';
import 'dart:collection' show HashMap; import 'dart:collection' show HashMap;
import 'dart:convert'; import 'dart:convert';
import 'package:angel3_container/angel3_container.dart'; import 'package:angel3_container/angel3_container.dart';
import 'package:angel3_container/mirrors.dart';
import 'package:angel3_http_exception/angel3_http_exception.dart'; import 'package:angel3_http_exception/angel3_http_exception.dart';
import 'package:angel3_route/angel3_route.dart'; import 'package:angel3_route/angel3_route.dart';
import 'package:belatuk_combinator/belatuk_combinator.dart'; import 'package:belatuk_combinator/belatuk_combinator.dart';
@ -21,17 +22,44 @@ import 'service.dart';
//final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)'); //final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
/// A function that configures an [Angel] server in some way. /// A function that configures an [Angel] server.
typedef AngelConfigurer = FutureOr<void> Function(Angel app); typedef AngelConfigurer = FutureOr<void> Function(Angel app);
/// A function that asynchronously generates a view from the given path and data. /// A function that asynchronously generates a view from the given path and data.
typedef ViewGenerator = FutureOr<String> Function(String path, typedef ViewGenerator = FutureOr<String> Function(String path,
[Map<String, dynamic>? data]); [Map<String, dynamic>? data]);
/// A function that handles error
typedef AngelErrorHandler = dynamic Function(
AngelHttpException e, RequestContext req, ResponseContext res);
/// The default error handler for [Angel] server
Future<bool> _defaultErrorHandler(
AngelHttpException e, RequestContext req, ResponseContext res) async {
if (!req.accepts('text/html', strict: true) &&
(req.accepts('application/json') ||
req.accepts('application/javascript'))) {
await res.json(e.toJson());
return Future.value(false);
} else {
res.contentType = MediaType('text', 'html', {'charset': 'utf8'});
res.statusCode = e.statusCode;
res.write('<!DOCTYPE html><html><head><title>${e.message}</title>');
res.write('</head><body><h1>${e.message}</h1><ul>');
for (var error in e.errors) {
res.write('<li>$error</li>');
}
res.write('</ul></body></html>');
return Future.value(false);
}
}
/// A powerful real-time/REST/MVC server class. /// A powerful real-time/REST/MVC server class.
class Angel extends Routable { class Angel extends Routable {
static ViewGenerator noViewEngineConfigured = static Future<String> _noViewEngineConfigured(String view, [Map? data]) =>
(String view, [Map? data]) => 'No view engine has been configured yet.'; Future.value('No view engine has been configured yet.');
final List<Angel> _children = []; final List<Angel> _children = [];
final Map< final Map<
@ -114,7 +142,7 @@ class Angel extends Routable {
/// A [Map] of application-specific data that can be accessed by any /// A [Map] of application-specific data that can be accessed by any
/// piece of code that can see this [Angel] instance. /// piece of code that can see this [Angel] instance.
/// ///
/// Packages like `package:angel_configuration` populate this map /// Packages like `package:angel3_configuration` populate this map
/// for you. /// for you.
@override @override
final Map configuration = {}; final Map configuration = {};
@ -122,31 +150,10 @@ class Angel extends Routable {
/// A function that renders views. /// A function that renders views.
/// ///
/// Called by [ResponseContext]@`render`. /// Called by [ResponseContext]@`render`.
ViewGenerator? viewGenerator = noViewEngineConfigured; ViewGenerator? viewGenerator = _noViewEngineConfigured;
/// The handler currently configured to run on [AngelHttpException]s. /// The handler currently configured to run on [AngelHttpException]s.
Function(AngelHttpException e, RequestContext req, ResponseContext res) AngelErrorHandler errorHandler = _defaultErrorHandler;
errorHandler =
(AngelHttpException e, RequestContext req, ResponseContext res) {
if (!req.accepts('text/html', strict: true) &&
(req.accepts('application/json') ||
req.accepts('application/javascript'))) {
res.json(e.toJson());
return;
}
res.contentType = MediaType('text', 'html', {'charset': 'utf8'});
res.statusCode = e.statusCode; // ?? 200;
res.write('<!DOCTYPE html><html><head><title>${e.message}</title>');
res.write('</head><body><h1>${e.message}</h1><ul>');
for (var error in e.errors) {
res.write('<li>$error</li>');
}
res.write('</ul></body></html>');
res.close();
};
@override @override
Route<RequestHandler> addRoute( Route<RequestHandler> addRoute(
@ -184,12 +191,12 @@ class Angel extends Routable {
/// Loads some base dependencies into the service container. /// Loads some base dependencies into the service container.
void bootstrapContainer() { void bootstrapContainer() {
if (runtimeType != Angel) { if (runtimeType != Angel) {
container?.registerSingleton(this); container.registerSingleton(this);
} }
container?.registerSingleton<Angel>(this); container.registerSingleton<Angel>(this);
container?.registerSingleton<Routable>(this); container.registerSingleton<Routable>(this);
container?.registerSingleton<Router>(this); container.registerSingleton<Router>(this);
} }
/// Shuts down the server, and closes any open [StreamController]s. /// Shuts down the server, and closes any open [StreamController]s.
@ -202,7 +209,7 @@ class Angel extends Routable {
}); });
super.close(); super.close();
viewGenerator = noViewEngineConfigured; viewGenerator = _noViewEngineConfigured;
_preContained.clear(); _preContained.clear();
handlerCache.clear(); handlerCache.clear();
encoders.clear(); encoders.clear();
@ -315,6 +322,7 @@ class Angel extends Routable {
/// the execution will be faster, as the injection requirements were stored beforehand. /// the execution will be faster, as the injection requirements were stored beforehand.
Future runContained(Function handler, RequestContext req, ResponseContext res, Future runContained(Function handler, RequestContext req, ResponseContext res,
[Container? container]) { [Container? container]) {
container ??= Container(MirrorsReflector());
return Future.sync(() { return Future.sync(() {
if (_preContained.containsKey(handler)) { if (_preContained.containsKey(handler)) {
return handleContained(handler, _preContained[handler]!, container)( return handleContained(handler, _preContained[handler]!, container)(
@ -328,10 +336,11 @@ class Angel extends Routable {
/// Runs with DI, and *always* reflects. Prefer [runContained]. /// Runs with DI, and *always* reflects. Prefer [runContained].
Future runReflected(Function handler, RequestContext req, ResponseContext res, Future runReflected(Function handler, RequestContext req, ResponseContext res,
[Container? container]) { [Container? container]) {
container ??= req.container ?? res.app!.container; container ??=
req.container ?? res.app?.container ?? Container(ThrowingReflector());
var h = handleContained( var h = handleContained(
handler, handler,
_preContained[handler] = preInject(handler, container!.reflector), _preContained[handler] = preInject(handler, container.reflector),
container); container);
return Future.sync(() => h(req, res)); return Future.sync(() => h(req, res));
// return closureMirror.apply(args).reflectee; // return closureMirror.apply(args).reflectee;
@ -350,7 +359,7 @@ class Angel extends Routable {
/// ///
/// If you are on `Dart >=2.0.0`, simply call `mountController<T>()`. /// If you are on `Dart >=2.0.0`, simply call `mountController<T>()`.
Future<T> mountController<T extends Controller>([Type? type]) { Future<T> mountController<T extends Controller>([Type? type]) {
var controller = container!.make<T>(type); var controller = container.make<T>(type);
return configure(controller.configureServer).then((_) => controller); return configure(controller.configureServer).then((_) => controller);
} }
@ -392,7 +401,7 @@ class Angel extends Routable {
} }
bootstrapContainer(); bootstrapContainer();
viewGenerator ??= noViewEngineConfigured; viewGenerator ??= _noViewEngineConfigured;
serializer ??= json.encode; serializer ??= json.encode;
} }
} }

View file

@ -68,7 +68,20 @@ class Service<Id, Data> extends Routable {
List<RequestHandler> get bootstrappers => []; List<RequestHandler> get bootstrappers => [];
/// The [Angel] app powering this service. /// The [Angel] app powering this service.
Angel? app; Angel? _app;
Angel get app {
if (_app == null) {
throw ArgumentError("Angel is not initialized");
}
return _app!;
}
set app(Angel angel) {
_app = angel;
}
bool get isAppActive => _app != null;
/// Closes this service, including any database connections or stream controllers. /// Closes this service, including any database connections or stream controllers.
@override @override
@ -223,12 +236,12 @@ class Service<Id, Data> extends Routable {
var handlers = List<RequestHandler>.from(handlerss); var handlers = List<RequestHandler>.from(handlerss);
// Add global middleware if declared on the instance itself // Add global middleware if declared on the instance itself
var before = getAnnotation<Middleware>(service, app!.container!.reflector); var before = getAnnotation<Middleware>(service, app.container.reflector);
if (before != null) handlers.addAll(before.handlers); if (before != null) handlers.addAll(before.handlers);
var indexMiddleware = var indexMiddleware =
getAnnotation<Middleware>(service.index, app!.container!.reflector); getAnnotation<Middleware>(service.index, app.container.reflector);
get('/', (req, res) { get('/', (req, res) {
return index(mergeMap([ return index(mergeMap([
{'query': req.queryParameters}, {'query': req.queryParameters},
@ -241,7 +254,7 @@ class Service<Id, Data> extends Routable {
]); ]);
var createMiddleware = var createMiddleware =
getAnnotation<Middleware>(service.create, app!.container!.reflector); getAnnotation<Middleware>(service.create, app.container.reflector);
post('/', (req, ResponseContext res) { post('/', (req, ResponseContext res) {
return req.parseBody().then((_) async { return req.parseBody().then((_) async {
return await create( return await create(
@ -261,7 +274,7 @@ class Service<Id, Data> extends Routable {
]); ]);
var readMiddleware = var readMiddleware =
getAnnotation<Middleware>(service.read, app!.container!.reflector); getAnnotation<Middleware>(service.read, app.container.reflector);
get('/:id', (req, res) { get('/:id', (req, res) {
return read( return read(
@ -277,7 +290,7 @@ class Service<Id, Data> extends Routable {
]); ]);
var modifyMiddleware = var modifyMiddleware =
getAnnotation<Middleware>(service.modify, app!.container!.reflector); getAnnotation<Middleware>(service.modify, app.container.reflector);
patch('/:id', (req, res) { patch('/:id', (req, res) {
return req.parseBody().then((_) async { return req.parseBody().then((_) async {
@ -296,7 +309,7 @@ class Service<Id, Data> extends Routable {
]); ]);
var updateMiddleware = var updateMiddleware =
getAnnotation<Middleware>(service.update, app!.container!.reflector); getAnnotation<Middleware>(service.update, app.container.reflector);
post('/:id', (req, res) { post('/:id', (req, res) {
return req.parseBody().then((_) async { return req.parseBody().then((_) async {
return await update( return await update(
@ -330,7 +343,7 @@ class Service<Id, Data> extends Routable {
]); ]);
var removeMiddleware = var removeMiddleware =
getAnnotation<Middleware>(service.remove, app!.container!.reflector); getAnnotation<Middleware>(service.remove, app.container.reflector);
delete('/', (req, res) { delete('/', (req, res) {
return remove( return remove(
'' as Id, '' as Id,

View file

@ -15,6 +15,8 @@ import 'http_response_context.dart';
final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)'); final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
typedef ServerGeneratorType = Future<HttpServer> Function(dynamic, int);
/// Adapts `dart:io`'s [HttpServer] to serve Angel. /// Adapts `dart:io`'s [HttpServer] to serve Angel.
class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer, class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
HttpRequestContext, HttpResponseContext> { HttpRequestContext, HttpResponseContext> {
@ -27,8 +29,7 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
scheme: 'http', host: server?.address.address, port: server?.port); scheme: 'http', host: server?.address.address, port: server?.port);
} }
AngelHttp._(Angel app, AngelHttp._(Angel app, ServerGeneratorType serverGenerator, bool useZone)
Future<HttpServer> Function(dynamic, int) serverGenerator, bool useZone)
: super(app, serverGenerator, useZone: useZone); : super(app, serverGenerator, useZone: useZone);
factory AngelHttp(Angel app, {bool useZone = true}) { factory AngelHttp(Angel app, {bool useZone = true}) {
@ -36,8 +37,7 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
} }
/// An instance mounted on a server started by the [serverGenerator]. /// An instance mounted on a server started by the [serverGenerator].
factory AngelHttp.custom( factory AngelHttp.custom(Angel app, ServerGeneratorType serverGenerator,
Angel app, Future<HttpServer> Function(dynamic, int) serverGenerator,
{bool useZone = true}) { {bool useZone = true}) {
return AngelHttp._(app, serverGenerator, useZone); return AngelHttp._(app, serverGenerator, useZone);
} }

View file

@ -77,7 +77,7 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
/// Magically transforms an [HttpRequest] into a [RequestContext]. /// Magically transforms an [HttpRequest] into a [RequestContext].
static Future<HttpRequestContext> from( static Future<HttpRequestContext> from(
HttpRequest request, Angel app, String path) { HttpRequest request, Angel app, String path) {
var ctx = HttpRequestContext().._container = app.container!.createChild(); var ctx = HttpRequestContext().._container = app.container.createChild();
var override = request.method; var override = request.method;

View file

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:angel3_container/src/container.dart'; import 'package:angel3_container/angel3_container.dart';
import 'package:angel3_framework/angel3_framework.dart'; import 'package:angel3_framework/angel3_framework.dart';
import 'package:collection/collection.dart' show IterableExtension; import 'package:collection/collection.dart' show IterableExtension;
import 'package:http2/transport.dart'; import 'package:http2/transport.dart';
@ -35,7 +35,7 @@ class Http2RequestContext extends RequestContext<ServerTransportStream?> {
Map<String, MockHttpSession> sessions, Map<String, MockHttpSession> sessions,
Uuid uuid) { Uuid uuid) {
var c = Completer<Http2RequestContext>(); var c = Completer<Http2RequestContext>();
var req = Http2RequestContext._(app.container!.createChild()) var req = Http2RequestContext._(app.container.createChild())
..app = app ..app = app
.._socket = socket .._socket = socket
.._stream = stream; .._stream = stream;

View file

@ -3,7 +3,7 @@ library performance.hello;
import 'dart:io'; import 'dart:io';
Future<Null> main() { Future<void> main() {
return HttpServer.bind('127.0.0.1', 3000, shared: true).then((server) { return HttpServer.bind('127.0.0.1', 3000, shared: true).then((server) {
print('Listening at http://${server.address.address}:${server.port}'); print('Listening at http://${server.address.address}:${server.port}');

View file

@ -4,13 +4,13 @@ description: A high-powered HTTP server extensible framework with dependency inj
homepage: https://angel3-framework.web.app/ homepage: https://angel3-framework.web.app/
repository: https://github.com/dukefirehawk/angel/tree/master/packages/framework repository: https://github.com/dukefirehawk/angel/tree/master/packages/framework
environment: environment:
sdk: '>=2.12.0 <3.0.0' sdk: '>=2.15.0 <3.0.0'
dependencies: dependencies:
angel3_container: ^3.1.0 angel3_container: ^6.0.0
angel3_http_exception: ^3.0.0 angel3_http_exception: ^6.0.0
angel3_model: ^3.1.0 angel3_model: ^6.0.0
angel3_route: ^5.2.0 angel3_route: ^6.0.0
angel3_mock_request: ^2.0.0 angel3_mock_request: ^6.0.0
belatuk_merge_map: ^3.0.0 belatuk_merge_map: ^3.0.0
belatuk_combinator: ^3.0.0 belatuk_combinator: ^3.0.0
belatuk_http_server: ^2.1.0 belatuk_http_server: ^2.1.0

View file

@ -85,8 +85,8 @@ void main() {
res.redirectToAction('TodoController@foo', {'foo': 'world'})); res.redirectToAction('TodoController@foo', {'foo': 'world'}));
// Register as a singleton, just for the purpose of this test // Register as a singleton, just for the purpose of this test
if (!app.container!.has<TodoController>()) { if (!app.container.has<TodoController>()) {
app.container!.registerSingleton(todoController = TodoController()); app.container.registerSingleton(todoController = TodoController());
} }
// Using mountController<T>(); // Using mountController<T>();
@ -98,7 +98,7 @@ void main() {
// Until https://github.com/angel-dart/route/issues/28 is closed, // Until https://github.com/angel-dart/route/issues/28 is closed,
// this will need to be done by manually mounting the router. // this will need to be done by manually mounting the router.
var subRouter = Router<RequestHandler>(); var subRouter = Router<RequestHandler>();
await todoController.applyRoutes(subRouter, app.container!.reflector); await todoController.applyRoutes(subRouter, app.container.reflector);
app.mount('/ctrl_group', subRouter); app.mount('/ctrl_group', subRouter);
print(app.controllers); print(app.controllers);
@ -165,7 +165,7 @@ void main() {
test('named actions', () async { test('named actions', () async {
var response = await client.get(Uri.parse('$url/redirect')); var response = await client.get(Uri.parse('$url/redirect'));
print('Response: ${response.body}'); print('Response: ${response.body}');
expect(response.body, equals('Hello, \"world!\"')); expect(response.body, equals('Hello, "world!"'));
}); });
group('optional expose', () { group('optional expose', () {

View file

@ -25,8 +25,8 @@ void main() {
client = http.Client(); client = http.Client();
// Inject some todos // Inject some todos
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 utf8.decoder.bind(req.body!).join(); var text = await utf8.decoder.bind(req.body!).join();
return Foo(text); return Foo(text);

View file

@ -135,8 +135,8 @@ void main() {
var type = e.isBefore ? 'before' : 'after'; var type = e.isBefore ? 'before' : 'after';
print('Params to $type ${e.eventName}: ${e.params}'); print('Params to $type ${e.eventName}: ${e.params}');
expect(e.params, isMap); expect(e.params, isMap);
expect(e.params?.keys, contains('provider')); expect(e.params.keys, contains('provider'));
expect(e.params?['provider'], const IsInstanceOf<Providers>()); expect(e.params['provider'], const IsInstanceOf<Providers>());
} }
svc svc

View file

@ -8,7 +8,7 @@ environment:
dependencies: dependencies:
charcode: ^1.2.0 charcode: ^1.2.0
dev_dependencies: dev_dependencies:
angel3_framework: ^4.2.0 angel3_framework: ^6.0.0
http: ^0.13.2 http: ^0.13.2
test: ^1.17.4 test: ^1.17.4
lints: ^1.0.0 lints: ^1.0.0

View file

@ -3,6 +3,7 @@
## 3.1.2 ## 3.1.2
* Updated repo link * Updated repo link
* Fixed null safety warnings
## 3.1.1 ## 3.1.1

View file

@ -8,15 +8,15 @@ void main(List<String> args) => Runner('example', configureServer).run(args);
Future configureServer(Angel app) async { Future configureServer(Angel app) async {
// Use the injected `pub_sub.Client` to send messages. // Use the injected `pub_sub.Client` to send messages.
var client = app.container?.make<pub_sub.Client>(); var client = app.container.make<pub_sub.Client>();
var greeting = 'Hello! This is the default greeting.'; var greeting = 'Hello! This is the default greeting.';
// We can listen for an event to perform some behavior. // We can listen for an event to perform some behavior.
// //
// Here, we use message passing to synchronize some common state. // Here, we use message passing to synchronize some common state.
var onGreetingChanged = await client?.subscribe('greeting_changed'); var onGreetingChanged = await client.subscribe('greeting_changed');
onGreetingChanged onGreetingChanged
?.cast<String>() .cast<String>()
.listen((newGreeting) => greeting = newGreeting); .listen((newGreeting) => greeting = newGreeting);
// Add some routes... // Add some routes...
@ -33,7 +33,7 @@ Future configureServer(Angel app) async {
// This route will push a new value for `greeting`. // This route will push a new value for `greeting`.
app.get('/change_greeting/:newGreeting', (req, res) { app.get('/change_greeting/:newGreeting', (req, res) {
greeting = (req.params['newGreeting'] as String? ?? ''); greeting = (req.params['newGreeting'] as String? ?? '');
client?.publish('greeting_changed', greeting); client.publish('greeting_changed', greeting);
return 'Changed greeting -> $greeting'; return 'Changed greeting -> $greeting';
}); });

View file

@ -233,8 +233,8 @@ _ ___ | /| / / /_/ / _ /___ _ /___
pub_sub.IsolateClient('client${argsWithId.id}', args.pubSubSendPort); pub_sub.IsolateClient('client${argsWithId.id}', args.pubSubSendPort);
var app = Angel(reflector: args.reflector) var app = Angel(reflector: args.reflector)
..container!.registerSingleton<pub_sub.Client>(client) ..container.registerSingleton<pub_sub.Client>(client)
..container!.registerSingleton(InstanceInfo(id: argsWithId.id)); ..container.registerSingleton(InstanceInfo(id: argsWithId.id));
app.shutdownHooks.add((_) => client.close()); app.shutdownHooks.add((_) => client.close());

View file

@ -1,5 +1,9 @@
# Change Log # Change Log
## 3.0.0-dev.3
* Fixed null safety warnings
## 3.0.0-dev.2 ## 3.0.0-dev.2
* Updated to use `package:belatuk_pretty_logging` * Updated to use `package:belatuk_pretty_logging`

View file

@ -106,7 +106,7 @@ class AngelShelf extends Driver<shelf.Request, ShelfResponseContext?,
var path = request.url.path.replaceAll(_straySlashes, ''); var path = request.url.path.replaceAll(_straySlashes, '');
if (path.isEmpty) path = '/'; if (path.isEmpty) path = '/';
var rq = var rq =
ShelfRequestContext(app, app.container!.createChild(), request, path); ShelfRequestContext(app, app.container.createChild(), request, path);
return Future.value(rq); return Future.value(rq);
} }

View file

@ -1,5 +1,5 @@
name: angel3_shelf name: angel3_shelf
version: 3.0.0-dev.2 version: 3.0.0-dev.3
description: Shelf interop with Angel3. Use this to wrap existing server code. description: Shelf interop with Angel3. Use this to wrap existing server code.
homepage: https://angel3-framework.web.app/ homepage: https://angel3-framework.web.app/
repository: https://github.com/dukefirehawk/angel/tree/master/packages/shelf repository: https://github.com/dukefirehawk/angel/tree/master/packages/shelf