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 @@
-
+
+
+
+
@@ -192,10 +196,10 @@
DEFINITION_ORDER
-
-
-
-
+
+
+
+
@@ -215,27 +219,27 @@
-
+
-
+
-
+
-
+
-
+
@@ -245,11 +249,11 @@
-
+
-
+
@@ -259,11 +263,11 @@
-
+
-
+
@@ -277,11 +281,11 @@
-
+
-
+
@@ -312,6 +316,7 @@
+
@@ -325,16 +330,13 @@
-
+
-
-
-
@@ -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'));
});
});
}