diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index fd29c844..c12960e2 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -5,438 +5,438 @@ - - - - - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml index a1c33e62..51942706 100644 --- a/.idea/libraries/Dart_SDK.xml +++ b/.idea/libraries/Dart_SDK.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml index 406d4377..fe3e59d4 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,8 @@ - + + \ No newline at end of file diff --git a/.idea/runConfigurations/All_Tests__for_coverage_.xml b/.idea/runConfigurations/All_Tests__for_coverage_.xml new file mode 100644 index 00000000..c5727acc --- /dev/null +++ b/.idea/runConfigurations/All_Tests__for_coverage_.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d46447e8..e22f2392 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,10 +2,19 @@ + + + + + + + + + @@ -17,6 +26,9 @@ + + + @@ -29,8 +41,8 @@ - - + + @@ -39,8 +51,8 @@ - - + + @@ -48,20 +60,10 @@ - - - - - - - - - - - + @@ -73,9 +75,9 @@ - + - + @@ -86,59 +88,56 @@ - - - + + + + + - - + + - - + + - + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - + + + BEFORE @@ -155,6 +154,8 @@ reopen REDIRECT close( + status + createdAt _isClosed @@ -174,12 +175,15 @@ - @@ -215,27 +219,27 @@ - + - - - - @@ -245,11 +249,11 @@ - - @@ -259,11 +263,11 @@ - - @@ -277,11 +281,11 @@ - - @@ -312,6 +316,7 @@ + - + - - - @@ -357,12 +359,6 @@ - - @@ -401,12 +397,13 @@ false - + + @@ -432,6 +429,7 @@ + 1481237183504 @@ -514,9 +512,6 @@ - - - @@ -526,6 +521,9 @@ + + + @@ -546,7 +544,7 @@ - @@ -558,28 +556,29 @@ - + - + - + - + - + - - + + - + + @@ -608,51 +607,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -676,7 +630,7 @@ - + @@ -744,7 +698,7 @@ - + @@ -849,20 +803,6 @@ - - - - - - - - - - - - - - @@ -877,13 +817,6 @@ - - - - - - - @@ -891,13 +824,6 @@ - - - - - - - @@ -905,79 +831,167 @@ - + - - - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -987,9 +1001,9 @@ - + - + diff --git a/README.md b/README.md index 8ae7647e..94276549 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # angel_framework -[![pub 1.0.2+4](https://img.shields.io/badge/pub-1.0.2+4-brightgreen.svg)](https://pub.dartlang.org/packages/angel_framework) +[![pub 1.0.2+5](https://img.shields.io/badge/pub-1.0.2+5-brightgreen.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) A high-powered HTTP server with support for dependency injection, sophisticated routing and more. diff --git a/lib/hooks.dart b/lib/hooks.dart index 3e7c7ee0..2f4a9ed6 100644 --- a/lib/hooks.dart +++ b/lib/hooks.dart @@ -215,12 +215,11 @@ HookedServiceEventListener disable([provider]) { /// Serializes the current time to `e.data` or `e.result`. /// You can provide an [assign] function to set the property on your object, and skip reflection. +/// If [serialize] is `true` (default), then the set date will be a `String`. If not, a raw `DateTime` will be used. /// /// Default key: `createdAt` -HookedServiceEventListener addCreatedAt({ - assign(obj, String now), - String key, -}) { +HookedServiceEventListener addCreatedAt( + {assign(obj, String now), String key, bool serialize: true}) { var name = key?.isNotEmpty == true ? key : 'createdAt'; return (HookedServiceEvent e) async { @@ -240,7 +239,8 @@ HookedServiceEventListener addCreatedAt({ } } - var now = new DateTime.now().toUtc().toIso8601String(); + var d = new DateTime.now().toUtc(); + var now = serialize == false ? d : d.toIso8601String(); normalize(obj) async { if (obj != null) { @@ -252,8 +252,7 @@ HookedServiceEventListener addCreatedAt({ } } - if (e.params?.containsKey('provider') == true) - await normalize(e.isBefore ? e.data : e.result); + await normalize(e.isBefore ? e.data : e.result); }; } @@ -266,12 +265,12 @@ HookedServiceEventListener addUpatedAt({ addUpdatedAt(assign: assign, key: key); /// Serializes the current time to `e.data` or `e.result`. -/// You can provide an [assign] function to set the property on your object, and skip reflection./// -/// Default key: `createdAt` -HookedServiceEventListener addUpdatedAt({ - assign(obj, String now), - String key, -}) { +/// You can provide an [assign] function to set the property on your object, and skip reflection. +/// If [serialize] is `true` (default), then the set date will be a `String`. If not, a raw `DateTime` will be used. +/// +/// Default key: `updatedAt` +HookedServiceEventListener addUpdatedAt( + {assign(obj, String now), String key, bool serialize: true}) { var name = key?.isNotEmpty == true ? key : 'updatedAt'; return (HookedServiceEvent e) async { @@ -291,7 +290,8 @@ HookedServiceEventListener addUpdatedAt({ } } - var now = new DateTime.now().toUtc().toIso8601String(); + var d = new DateTime.now().toUtc(); + var now = serialize == false ? d : d.toIso8601String(); normalize(obj) async { if (obj != null) { @@ -303,7 +303,6 @@ HookedServiceEventListener addUpdatedAt({ } } - if (e.params?.containsKey('provider') == true) - await normalize(e.isBefore ? e.data : e.result); + await normalize(e.isBefore ? e.data : e.result); }; } diff --git a/lib/src/http/map_service.dart b/lib/src/http/map_service.dart index a4b3909c..cfe62f51 100644 --- a/lib/src/http/map_service.dart +++ b/lib/src/http/map_service.dart @@ -22,7 +22,7 @@ class MapService extends Service { @override Future index([Map params]) async { - if (allowRemoveAll != true || params == null || params['query'] is! Map) + if (allowQuery == false || params == null || params['query'] is! Map) return items; else { Map query = params['query']; diff --git a/lib/src/http/response_context.dart b/lib/src/http/response_context.dart index f126d06e..9c49ca43 100644 --- a/lib/src/http/response_context.dart +++ b/lib/src/http/response_context.dart @@ -11,7 +11,7 @@ import 'server.dart' show Angel; import 'controller.dart'; final RegExp _contentType = - new RegExp(r'([^/\n]+)\/\s*([^;\n]+)\s*(;\s*charset=([^$;\n]+))?'); +new RegExp(r'([^/\n]+)\/\s*([^;\n]+)\s*(;\s*charset=([^$;\n]+))?'); final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); @@ -22,7 +22,9 @@ typedef String ResponseSerializer(data); class ResponseContext extends Extensible { final _LockableBytesBuilder _buffer = new _LockableBytesBuilder(); final Map _headers = {HttpHeaders.SERVER: 'angel'}; - bool _isOpen = true, _isClosed = false; + bool _isOpen = true, + _isClosed = false; + int _statusCode = 200; /// The [Angel] instance that is sending a response. Angel app; @@ -57,7 +59,14 @@ class ResponseContext extends Extensible { ResponseSerializer serializer = god.serialize; /// This response's status code. - int statusCode = 200; + int get statusCode => _statusCode; + + void set statusCode(int value) { + if (_isClosed) + throw _closed(); + else + _statusCode = value ?? 200; + } /// Can we still write to this response? bool get isOpen => _isOpen; @@ -115,7 +124,7 @@ class ResponseContext extends Extensible { if (!_isOpen) throw _closed(); headers["Content-Disposition"] = - 'attachment; filename="${filename ?? file.path}"'; + 'attachment; filename="${filename ?? file.path}"'; headers[HttpHeaders.CONTENT_TYPE] = lookupMimeType(file.path); headers[HttpHeaders.CONTENT_LENGTH] = file.lengthSync().toString(); buffer.add(await file.readAsBytes()); @@ -194,7 +203,7 @@ class ResponseContext extends Extensible { headers ..[HttpHeaders.CONTENT_TYPE] = ContentType.HTML.toString() ..[HttpHeaders.LOCATION] = - url is String ? url : app.navigate(url, absolute: absolute); + url is String ? url : app.navigate(url, absolute: absolute); statusCode = code ?? 302; write(''' @@ -252,7 +261,7 @@ class ResponseContext extends Extensible { "Controller redirects must take the form of 'Controller@action'. You gave: $action"); Controller controller = - app.controller(split[0].replaceAll(_straySlashes, '')); + app.controller(split[0].replaceAll(_straySlashes, '')); if (controller == null) throw new Exception("Could not find a controller named '${split[0]}'"); @@ -264,7 +273,11 @@ class ResponseContext extends Extensible { "Controller '${split[0]}' does not contain any action named '${split[1]}'"); final head = - controller.findExpose().path.toString().replaceAll(_straySlashes, ''); + controller + .findExpose() + .path + .toString() + .replaceAll(_straySlashes, ''); final tail = matched.makeUri(params).replaceAll(_straySlashes, ''); redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code); @@ -300,9 +313,9 @@ class ResponseContext extends Extensible { /// You can optionally transform the file stream with a [codec]. Future streamFile(File file, {int chunkSize, - int sleepMs: 0, - bool resumable: true, - Codec, List> codec}) async { + int sleepMs: 0, + bool resumable: true, + Codec, List> codec}) async { if (_isClosed) throw _closed(); headers[HttpHeaders.CONTENT_TYPE] = lookupMimeType(file.path); @@ -330,7 +343,9 @@ class ResponseContext extends Extensible { abstract class _LockableBytesBuilder extends BytesBuilder { factory _LockableBytesBuilder() => new _LockableBytesBuilderImpl(); + void _lock(); + void _reopen(); } diff --git a/pubspec.yaml b/pubspec.yaml index 6dec5e81..6aa20635 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_framework -version: 1.0.2+4 +version: 1.0.2+5 description: A high-powered HTTP server with DI, routing and more. author: Tobe O homepage: https://github.com/angel-dart/angel_framework diff --git a/test/all.dart b/test/all.dart new file mode 100644 index 00000000..da1c11ae --- /dev/null +++ b/test/all.dart @@ -0,0 +1,21 @@ +import 'controller_test.dart' as controller; +import 'di_test.dart' as di; +import 'general_test.dart' as general; +import 'hooked_test.dart' as hooked; +import 'routing_test.dart' as routing; +import 'serialize_test.dart' as serialize; +import 'services_test.dart' as services; +import 'util_test.dart' as util; +import 'package:test/test.dart'; + +/// For running with coverage +main() { + group('controller', controller.main); + group('di', di.main); + group('general', general.main); + group('hooked', hooked.main); + group('routing', routing.main); + group('serialize', serialize.main); + group('services', services.main); + group('util', util.main); +} \ No newline at end of file diff --git a/test/services_test.dart b/test/services_test.dart index ee376cbf..fa402f0a 100644 --- a/test/services_test.dart +++ b/test/services_test.dart @@ -32,6 +32,7 @@ main() { }); tearDown(() async { + await app.close(); app = null; url = null; client.close(); diff --git a/test/util_test.dart b/test/util_test.dart index 2d22fedd..8b112f25 100644 --- a/test/util_test.dart +++ b/test/util_test.dart @@ -9,24 +9,25 @@ class Foo { main() { group('Utilities', () { - Angel angel; + Angel app; setUp(() { - angel = new Angel(); + app = new Angel(); }); - tearDown(() { - angel = null; + tearDown(() async { + await app.close(); + app = null; }); test('can use app.properties like members', () { - angel.properties['hello'] = 'world'; - angel.properties['foo'] = () => 'bar'; - angel.properties['Foo'] = new Foo('bar'); + app.properties['hello'] = 'world'; + app.properties['foo'] = () => 'bar'; + app.properties['Foo'] = new Foo('bar'); - expect(angel.hello, equals('world')); - expect(angel.foo(), equals('bar')); - expect(angel.Foo.name, equals('bar')); + expect(app.hello, equals('world')); + expect(app.foo(), equals('bar')); + expect(app.Foo.name, equals('bar')); }); }); }