Will be done soon
This commit is contained in:
parent
9008e8cbe2
commit
a3f9d6ce28
7 changed files with 292 additions and 0 deletions
60
.gitignore
vendored
60
.gitignore
vendored
|
@ -25,3 +25,63 @@ doc/api/
|
|||
# Don't commit pubspec lock file
|
||||
# (Library packages only! Remove pattern if developing an application package)
|
||||
pubspec.lock
|
||||
### Dart template
|
||||
# See https://www.dartlang.org/tools/private-files.html
|
||||
|
||||
# Files and directories created by pub
|
||||
|
||||
# Files created by dart2js
|
||||
# (Most Dart developers will use pub build to compile Dart, use/modify these
|
||||
# rules if you intend to use dart2js directly
|
||||
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
|
||||
# differentiate from explicit Javascript files)
|
||||
|
||||
# Directory created by dartdoc
|
||||
|
||||
# Don't commit pubspec lock file
|
||||
# (Library packages only! Remove pattern if developing an application package)
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/dictionaries
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/dataSources.ids
|
||||
.idea/dataSources.xml
|
||||
.idea/dataSources.local.xml
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/gradle.xml
|
||||
.idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
|
6
.idea/runConfigurations/All_Tests.xml
Normal file
6
.idea/runConfigurations/All_Tests.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="All Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">
|
||||
<option name="filePath" value="$PROJECT_DIR$/test/all_tests.dart" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
10
lib/angel_mongo.dart
Normal file
10
lib/angel_mongo.dart
Normal file
|
@ -0,0 +1,10 @@
|
|||
library angel_mongo;
|
||||
import 'dart:async';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:json_god/json_god.dart';
|
||||
import 'package:merge_map/merge_map.dart';
|
||||
import 'package:mongo_dart/mongo_dart.dart';
|
||||
|
||||
part 'mongo_service.dart';
|
||||
|
||||
final _god = new God();
|
92
lib/mongo_service.dart
Normal file
92
lib/mongo_service.dart
Normal file
|
@ -0,0 +1,92 @@
|
|||
part of angel_mongo;
|
||||
|
||||
class MongoService extends Service {
|
||||
DbCollection collection;
|
||||
|
||||
MongoService(DbCollection this.collection);
|
||||
|
||||
Map _jsonify(Map doc) {
|
||||
Map result = {};
|
||||
for (var key in doc.keys) {
|
||||
if (doc[key] is ObjectId) {
|
||||
result[key] = doc[key].toHexString();
|
||||
} else result[key] = doc[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
_lastItem() async {
|
||||
return (await (await collection.find(
|
||||
where.sortBy('\$natural', descending: true))).toList())
|
||||
.map(_jsonify)
|
||||
.first;
|
||||
}
|
||||
|
||||
SelectorBuilder _makeQuery([Map params_]) {
|
||||
Map params = params_ ?? {};
|
||||
SelectorBuilder result = where.exists('_id');
|
||||
|
||||
for (var key in params.keys) {
|
||||
if (key == r'$sort') {
|
||||
if (params[key] is Map) {
|
||||
// If they send a map, then we'll sort by every key in the map
|
||||
for (String fieldName in params[key].keys.where((x) => x is String)) {
|
||||
var sorter = params[key][fieldName];
|
||||
if (sorter is num) {
|
||||
result = result.sortBy(fieldName, descending: sorter == -1);
|
||||
} else if (sorter is String) {
|
||||
result = result.sortBy(fieldName, descending: sorter == "-1");
|
||||
}
|
||||
}
|
||||
} else if (params[key] is String) {
|
||||
// If they send just a string, then we'll sort
|
||||
// by that, ascending
|
||||
result = result.sortBy(params[key]);
|
||||
}
|
||||
}
|
||||
|
||||
else if (key is String) {
|
||||
result = result.and(where.eq(key, params[key]));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List> index([Map params]) async {
|
||||
return await (await collection.find(_makeQuery(params)))
|
||||
.map(_jsonify)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future create(data, [Map params]) async {
|
||||
Map item = (data is Map) ? data : _god.serializeToMap(data);
|
||||
item = mergeMap([item, params]);
|
||||
item['createdAt'] = new DateTime.now();
|
||||
await collection.insert(item);
|
||||
return await _lastItem();
|
||||
}
|
||||
|
||||
@override
|
||||
Future read(id, [Map params]) async {
|
||||
ObjectId id_;
|
||||
try {
|
||||
id_ = (id is ObjectId) ? id : new ObjectId.fromHexString(
|
||||
id.toString());
|
||||
} catch (e) {
|
||||
throw new AngelHttpException.BadRequest();
|
||||
}
|
||||
|
||||
Map found = await collection.findOne(
|
||||
where.id(id_).and(_makeQuery(params)));
|
||||
|
||||
if (found == null) {
|
||||
throw new AngelHttpException.NotFound(
|
||||
message: 'No record found for ID ${id_.toHexString()}');
|
||||
}
|
||||
|
||||
return _jsonify(found);
|
||||
}
|
||||
}
|
12
pubspec.yaml
Normal file
12
pubspec.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
name: angel_mongo
|
||||
version: 1.0.0-dev
|
||||
description: Core libraries for the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
dependencies:
|
||||
angel_framework: ">=0.0.0-dev.17 < 0.1.0"
|
||||
json_god: ">=1.0.0 <2.0.0"
|
||||
mongo_dart: ">= 0.2.5+1 < 1.0.0"
|
||||
dev_dependencies:
|
||||
http: ">= 0.11.3 < 0.12.0"
|
||||
test: ">= 0.12.13 < 0.13.0"
|
106
test/all_tests.dart
Normal file
106
test/all_tests.dart
Normal file
|
@ -0,0 +1,106 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_mongo/angel_mongo.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_god/json_god.dart';
|
||||
import 'package:mongo_dart/mongo_dart.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
final headers = {
|
||||
HttpHeaders.ACCEPT: ContentType.JSON.mimeType,
|
||||
HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType
|
||||
};
|
||||
|
||||
wireHooked(HookedService hooked) {
|
||||
hooked.onCreated.listen((item) {
|
||||
print("Just created: $item");
|
||||
});
|
||||
}
|
||||
|
||||
main() {
|
||||
group('angel_mongo', () {
|
||||
Angel app = new Angel();
|
||||
http.Client client;
|
||||
God god = new God();
|
||||
Db db = new Db('mongodb://localhost:27017/angel_mongo');
|
||||
DbCollection testData;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
await db.open();
|
||||
testData = db.collection('test_data');
|
||||
// Delete anything before we start
|
||||
await testData.remove();
|
||||
var service = new MongoService(testData);
|
||||
var hooked = new HookedService(service);
|
||||
wireHooked(hooked);
|
||||
|
||||
app.use('/api', hooked);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
// Delete anything left over
|
||||
await testData.remove();
|
||||
await db.close();
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('insert items', () async {
|
||||
Map testUser = {'hello': 'world'};
|
||||
|
||||
var response = await client.post(
|
||||
"$url/api", body: god.serialize(testUser), headers: headers);
|
||||
expect(response.statusCode, equals(HttpStatus.OK));
|
||||
|
||||
response = await client.get("$url/api");
|
||||
expect(response.statusCode, 200);
|
||||
List<Map> users = god.deserialize(response.body);
|
||||
expect(users.length, equals(1));
|
||||
});
|
||||
|
||||
test('read item', () async {
|
||||
Map testUser = {'hello': 'world'};
|
||||
var response = await client.post(
|
||||
"$url/api", body: god.serialize(testUser), headers: headers);
|
||||
expect(response.statusCode, equals(HttpStatus.OK));
|
||||
Map created = god.deserialize(response.body);
|
||||
|
||||
response = await client.get("$url/api/${created['_id']}");
|
||||
expect(response.statusCode, equals(HttpStatus.OK));
|
||||
Map read = god.deserialize(response.body);
|
||||
expect(read['_id'], equals(created['_id']));
|
||||
expect(read['hello'], equals('world'));
|
||||
expect(read['createdAt'], isNot(null));
|
||||
});
|
||||
|
||||
test('modify item', () async {
|
||||
|
||||
});
|
||||
|
||||
test('update item', () async {
|
||||
|
||||
});
|
||||
|
||||
test('remove item', () async {
|
||||
|
||||
});
|
||||
|
||||
test('sort by string', () async {
|
||||
|
||||
});
|
||||
|
||||
test('sort by map', () async {
|
||||
|
||||
});
|
||||
|
||||
test('query parameters', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue