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
|
# Don't commit pubspec lock file
|
||||||
# (Library packages only! Remove pattern if developing an application package)
|
# (Library packages only! Remove pattern if developing an application package)
|
||||||
pubspec.lock
|
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