Updated framework
This commit is contained in:
parent
515c813900
commit
3df9010af0
19 changed files with 67 additions and 58 deletions
|
@ -1,3 +1,6 @@
|
|||
# 4.0.2
|
||||
* Updated README
|
||||
|
||||
# 4.0.1
|
||||
* Updated README
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# angel3_framework
|
||||
[![version](https://img.shields.io/badge/pub-v4.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_framework)
|
||||
[![version](https://img.shields.io/badge/pub-v4.0.2-brightgreen)](https://pub.dartlang.org/packages/angel3_framework)
|
||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# include: package:pedantic/analysis_options.yaml
|
||||
include: package:pedantic/analysis_options.yaml
|
||||
|
||||
analyzer:
|
||||
errors:
|
||||
always_declare_return_types: ignore
|
||||
|
|
|
@ -13,12 +13,15 @@ class AnonymousService<Id, Data> extends Service<Id, Data> {
|
|||
FutureOr<Data> Function(Id, Data, [Map<String, dynamic>?])? _modify, _update;
|
||||
|
||||
AnonymousService(
|
||||
{FutureOr<List<Data>> index([Map<String, dynamic>? params])?,
|
||||
FutureOr<Data> read(Id id, [Map<String, dynamic>? params])?,
|
||||
FutureOr<Data> create(Data data, [Map<String, dynamic>? params])?,
|
||||
FutureOr<Data> modify(Id id, Data data, [Map<String, dynamic>? params])?,
|
||||
FutureOr<Data> update(Id id, Data data, [Map<String, dynamic>? params])?,
|
||||
FutureOr<Data> remove(Id id, [Map<String, dynamic>? params])?,
|
||||
{FutureOr<List<Data>> Function([Map<String, dynamic>? params])? index,
|
||||
FutureOr<Data> Function(Id id, [Map<String, dynamic>? params])? read,
|
||||
FutureOr<Data> Function(Data data, [Map<String, dynamic>? params])?
|
||||
create,
|
||||
FutureOr<Data> Function(Id id, Data data, [Map<String, dynamic>? params])?
|
||||
modify,
|
||||
FutureOr<Data> Function(Id id, Data data, [Map<String, dynamic>? params])?
|
||||
update,
|
||||
FutureOr<Data> Function(Id id, [Map<String, dynamic>? params])? remove,
|
||||
FutureOr<Data> Function(RequestContext, ResponseContext)? readData})
|
||||
: super(readData: readData) {
|
||||
_index = index;
|
||||
|
|
|
@ -50,7 +50,7 @@ class Controller {
|
|||
Future<String> applyRoutes(
|
||||
Router<RequestHandler> router, Reflector reflector) async {
|
||||
// Load global expose decl
|
||||
var classMirror = reflector.reflectClass(this.runtimeType)!;
|
||||
var classMirror = reflector.reflectClass(runtimeType)!;
|
||||
Expose? exposeDecl = findExpose(reflector);
|
||||
|
||||
if (exposeDecl == null) {
|
||||
|
@ -60,7 +60,7 @@ class Controller {
|
|||
var routable = Routable();
|
||||
var m = router.mount(exposeDecl.path!, routable);
|
||||
_mountPoint = m;
|
||||
var typeMirror = reflector.reflectType(this.runtimeType);
|
||||
var typeMirror = reflector.reflectType(runtimeType);
|
||||
|
||||
// Pre-reflect methods
|
||||
var instanceMirror = reflector.reflectInstance(this);
|
||||
|
|
|
@ -45,7 +45,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
HookedService(this.inner) {
|
||||
// Clone app instance
|
||||
if (inner.app != null) this.app = inner.app;
|
||||
if (inner.app != null) app = inner.app;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -131,6 +131,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
applyListeners(inner.remove, afterRemoved, true);
|
||||
}
|
||||
|
||||
@override
|
||||
List<RequestHandler> get bootstrappers =>
|
||||
List<RequestHandler>.from(super.bootstrappers)
|
||||
..add((RequestContext req, ResponseContext res) {
|
||||
|
@ -140,6 +141,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
return true;
|
||||
});
|
||||
|
||||
@override
|
||||
void addRoutes([Service? s]) {
|
||||
super.addRoutes(s ?? inner);
|
||||
}
|
||||
|
@ -509,13 +511,13 @@ class HookedServiceEvent<Id, Data, T extends Service<Id, Data>> {
|
|||
Service? getService(Pattern path) => service.app!.findService(path);
|
||||
|
||||
bool _canceled = false;
|
||||
String _eventName;
|
||||
final String _eventName;
|
||||
Id? _id;
|
||||
bool _isAfter;
|
||||
final bool _isAfter;
|
||||
Data? data;
|
||||
Map<String, dynamic>? _params;
|
||||
RequestContext? _request;
|
||||
ResponseContext? _response;
|
||||
final RequestContext? _request;
|
||||
final ResponseContext? _response;
|
||||
var result;
|
||||
|
||||
String get eventName => _eventName;
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:string_scanner/string_scanner.dart';
|
|||
/// Parses a string into a [RegExp] that is matched against hostnames.
|
||||
class HostnameSyntaxParser {
|
||||
final SpanScanner _scanner;
|
||||
var _safe = RegExp(r"[0-9a-zA-Z-_:]+");
|
||||
final _safe = RegExp(r"[0-9a-zA-Z-_:]+");
|
||||
|
||||
HostnameSyntaxParser(String hostname)
|
||||
: _scanner = SpanScanner(hostname, sourceUrl: hostname);
|
||||
|
|
|
@ -71,8 +71,7 @@ class MapService extends Service<String?, Map<String, dynamic>> {
|
|||
[Map<String, dynamic>? params]) {
|
||||
return Future.value(items.firstWhere(_matchesId(id),
|
||||
orElse: (() => throw AngelHttpException.notFound(
|
||||
message: 'No record found for ID $id'))
|
||||
as Map<String, dynamic> Function()?));
|
||||
message: 'No record found for ID $id'))));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -112,9 +111,8 @@ class MapService extends Service<String?, Map<String, dynamic>> {
|
|||
var result = Map<String, dynamic>.from(item)..addAll(data);
|
||||
|
||||
if (autoIdAndDateFields == true) {
|
||||
result
|
||||
..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] =
|
||||
DateTime.now().toIso8601String();
|
||||
result[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] =
|
||||
DateTime.now().toIso8601String();
|
||||
}
|
||||
return Future.value(items[idx] = result);
|
||||
});
|
||||
|
|
|
@ -145,7 +145,9 @@ abstract class RequestContext<RawRequest> {
|
|||
List? get bodyAsList {
|
||||
if (!hasParsedBody) {
|
||||
throw StateError('The request body has not been parsed yet.');
|
||||
} else if (_bodyList == null) {
|
||||
// TODO: Relook at this
|
||||
//} else if (_bodyList == null) {
|
||||
} else if (_bodyList.isEmpty) {
|
||||
throw StateError('The request body, $_bodyObject, is not a List.');
|
||||
}
|
||||
|
||||
|
@ -258,9 +260,8 @@ abstract class RequestContext<RawRequest> {
|
|||
_hasParsedBody = true;
|
||||
|
||||
var contentBody = body;
|
||||
if (contentBody == null) {
|
||||
contentBody = Stream.empty();
|
||||
}
|
||||
//TODO: Relook at this
|
||||
contentBody ??= Stream.empty();
|
||||
|
||||
if (contentType.type == 'application' && contentType.subtype == 'json') {
|
||||
_uploadedFiles = [];
|
||||
|
|
|
@ -160,6 +160,7 @@ abstract class ResponseContext<RawResponse>
|
|||
}
|
||||
|
||||
/// Prevents more data from being written to the response, and locks it entire from further editing.
|
||||
@override
|
||||
Future<void> close() {
|
||||
if (buffer is LockableBytesBuilder) {
|
||||
(buffer as LockableBytesBuilder).lock();
|
||||
|
@ -326,9 +327,7 @@ abstract class ResponseContext<RawResponse>
|
|||
: MediaType.parse(mimeType);
|
||||
|
||||
if (correspondingRequest!.method != 'HEAD') {
|
||||
return this
|
||||
.addStream(file.openRead().cast<List<int>>())
|
||||
.then((_) => this.close());
|
||||
return addStream(file.openRead().cast<List<int>>()).then((_) => close());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,6 +355,7 @@ abstract class ResponseContext<RawResponse>
|
|||
}
|
||||
|
||||
/// Writes data to the response.
|
||||
@override
|
||||
void write(value, {Encoding? encoding}) {
|
||||
encoding ??= utf8;
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ class Routable extends Router<RequestHandler> {
|
|||
/// A set of [Service] objects that have been mapped into routes.
|
||||
Map<Pattern, Service> get services => _services;
|
||||
|
||||
StreamController<Service> _onService = StreamController<Service>.broadcast();
|
||||
final StreamController<Service> _onService =
|
||||
StreamController<Service>.broadcast();
|
||||
|
||||
/// Fired whenever a service is added to this instance.
|
||||
///
|
||||
|
@ -108,9 +109,7 @@ class Routable extends Router<RequestHandler> {
|
|||
}
|
||||
|
||||
final handlerSequence = <RequestHandler>[];
|
||||
if (middleware != null) {
|
||||
handlerSequence.addAll(middleware);
|
||||
}
|
||||
handlerSequence.addAll(middleware);
|
||||
handlerSequence.addAll(handlers);
|
||||
|
||||
return super.addRoute(method, path.toString(), handler,
|
||||
|
|
|
@ -71,6 +71,7 @@ class Service<Id, Data> extends Routable {
|
|||
Angel? app;
|
||||
|
||||
/// Closes this service, including any database connections or stream controllers.
|
||||
@override
|
||||
void close() {}
|
||||
|
||||
/// An optional [readData] function can be passed to handle non-map/non-json bodies.
|
||||
|
@ -230,7 +231,7 @@ class Service<Id, Data> extends Routable {
|
|||
Middleware? indexMiddleware =
|
||||
getAnnotation<Middleware>(service.index, app!.container!.reflector);
|
||||
get('/', (req, res) {
|
||||
return this.index(mergeMap([
|
||||
return index(mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
restProvider,
|
||||
req.serviceParams
|
||||
|
@ -246,15 +247,13 @@ class Service<Id, Data> extends Routable {
|
|||
getAnnotation<Middleware>(service.create, app!.container!.reflector);
|
||||
post('/', (req, ResponseContext res) {
|
||||
return req.parseBody().then((_) async {
|
||||
return await this
|
||||
.create(
|
||||
(await readData!(req, res))!,
|
||||
mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
restProvider,
|
||||
req.serviceParams
|
||||
]))
|
||||
.then((r) {
|
||||
return await create(
|
||||
(await readData!(req, res))!,
|
||||
mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
restProvider,
|
||||
req.serviceParams
|
||||
])).then((r) {
|
||||
res.statusCode = 201;
|
||||
return r;
|
||||
});
|
||||
|
@ -270,7 +269,7 @@ class Service<Id, Data> extends Routable {
|
|||
getAnnotation<Middleware>(service.read, app!.container!.reflector);
|
||||
|
||||
get('/:id', (req, res) {
|
||||
return this.read(
|
||||
return read(
|
||||
parseId<Id>(req.params['id']),
|
||||
mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
|
@ -289,7 +288,7 @@ class Service<Id, Data> extends Routable {
|
|||
|
||||
patch('/:id', (req, res) {
|
||||
return req.parseBody().then((_) async {
|
||||
return await this.modify(
|
||||
return await modify(
|
||||
parseId<Id>(req.params['id']),
|
||||
(await readData!(req, res))!,
|
||||
mergeMap([
|
||||
|
@ -309,7 +308,7 @@ class Service<Id, Data> extends Routable {
|
|||
getAnnotation<Middleware>(service.update, app!.container!.reflector);
|
||||
post('/:id', (req, res) {
|
||||
return req.parseBody().then((_) async {
|
||||
return await this.update(
|
||||
return await update(
|
||||
parseId<Id>(req.params['id']),
|
||||
(await readData!(req, res))!,
|
||||
mergeMap([
|
||||
|
@ -327,7 +326,7 @@ class Service<Id, Data> extends Routable {
|
|||
|
||||
put('/:id', (req, res) {
|
||||
return req.parseBody().then((_) async {
|
||||
return await this.update(
|
||||
return await update(
|
||||
parseId<Id>(req.params['id']),
|
||||
(await readData!(req, res))!,
|
||||
mergeMap([
|
||||
|
@ -346,7 +345,7 @@ class Service<Id, Data> extends Routable {
|
|||
Middleware? removeMiddleware =
|
||||
getAnnotation<Middleware>(service.remove, app!.container!.reflector);
|
||||
delete('/', (req, res) {
|
||||
return this.remove(
|
||||
return remove(
|
||||
'' as Id,
|
||||
mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
|
@ -361,7 +360,7 @@ class Service<Id, Data> extends Routable {
|
|||
: removeMiddleware.handlers.toList()));
|
||||
|
||||
delete('/:id', (req, res) {
|
||||
return this.remove(
|
||||
return remove(
|
||||
parseId<Id>(req.params['id']),
|
||||
mergeMap([
|
||||
{'query': req.queryParameters},
|
||||
|
|
|
@ -38,6 +38,7 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
|
|||
}
|
||||
|
||||
/// The underlying [HttpRequest] instance underneath this context.
|
||||
@override
|
||||
HttpRequest? get rawRequest => _io;
|
||||
|
||||
@override
|
||||
|
|
|
@ -168,7 +168,7 @@ class _FakeServerSocket extends Stream<Socket> implements ServerSocket {
|
|||
|
||||
@override
|
||||
Future<ServerSocket> close() async {
|
||||
(_ctrl.close());
|
||||
await (_ctrl.close());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -217,10 +217,13 @@ class _AngelHttp2ServerSocket extends Stream<SecureSocket>
|
|||
);
|
||||
}
|
||||
|
||||
@override
|
||||
InternetAddress get address => socket.address;
|
||||
|
||||
@override
|
||||
int get port => socket.port;
|
||||
|
||||
@override
|
||||
Future<SecureServerSocket> close() {
|
||||
_sub?.cancel();
|
||||
_fake.close();
|
||||
|
|
|
@ -126,9 +126,7 @@ class Http2RequestContext extends RequestContext<ServerTransportStream?> {
|
|||
// Apply session
|
||||
var dartSessId = cookies.firstWhereOrNull((c) => c.name == 'DARTSESSID');
|
||||
|
||||
if (dartSessId == null) {
|
||||
dartSessId = Cookie('DARTSESSID', uuid.v4());
|
||||
}
|
||||
dartSessId ??= Cookie('DARTSESSID', uuid.v4());
|
||||
|
||||
req._session = sessions.putIfAbsent(
|
||||
dartSessId.value,
|
||||
|
|
|
@ -9,6 +9,7 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
final Angel? app;
|
||||
final ServerTransportStream stream;
|
||||
|
||||
@override
|
||||
ServerTransportStream get rawResponse => stream;
|
||||
|
||||
LockableBytesBuilder? _buffer;
|
||||
|
|
|
@ -16,7 +16,7 @@ abstract class SafeCtrl<T> {
|
|||
|
||||
Future close();
|
||||
|
||||
void whenInitialized(void callback());
|
||||
void whenInitialized(void Function() callback);
|
||||
}
|
||||
|
||||
class _SingleSafeCtrl<T> implements SafeCtrl<T> {
|
||||
|
@ -60,7 +60,7 @@ class _SingleSafeCtrl<T> implements SafeCtrl<T> {
|
|||
}
|
||||
|
||||
@override
|
||||
void whenInitialized(void callback()) {
|
||||
void whenInitialized(void Function() callback) {
|
||||
if (!_initialized) {
|
||||
if (!_hasListener) {
|
||||
_initializer = callback;
|
||||
|
@ -110,7 +110,7 @@ class _BroadcastSafeCtrl<T> implements SafeCtrl<T> {
|
|||
}
|
||||
|
||||
@override
|
||||
void whenInitialized(void callback()) {
|
||||
void whenInitialized(void Function() callback) {
|
||||
if (!_initialized) {
|
||||
if (_listeners <= 0) {
|
||||
_initializer = callback;
|
||||
|
|
|
@ -20,7 +20,7 @@ T? getAnnotation<T>(obj, Reflector? reflector) {
|
|||
var methodMirror = reflector.reflectFunction(obj)!;
|
||||
return matchingAnnotation<T>(methodMirror.annotations);
|
||||
} else {
|
||||
var classMirror = reflector.reflectClass(obj.runtimeType as Type)!;
|
||||
var classMirror = reflector.reflectClass(obj.runtimeType)!;
|
||||
return matchingAnnotation<T>(classMirror.annotations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel3_framework
|
||||
version: 4.0.1
|
||||
version: 4.0.2
|
||||
description: A high-powered HTTP server with dependency injection, routing and much more.
|
||||
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/framework
|
||||
environment:
|
||||
|
@ -33,4 +33,4 @@ dev_dependencies:
|
|||
http: ^0.13.1
|
||||
io: ^1.0.0
|
||||
test: ^1.17.4
|
||||
|
||||
pedantic: ^1.11.0
|
||||
|
|
Loading…
Reference in a new issue