Merge pull request #2 from alextekartik/master

feat: use the new sembast store API
This commit is contained in:
Tobe Osakwe 2020-02-14 17:29:27 -05:00 committed by GitHub
commit eda2acc36a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 66 deletions

View file

@ -5,17 +5,17 @@ import 'package:logging/logging.dart';
import 'package:sembast/sembast_io.dart';
main() async {
var app = new Angel();
var app = Angel();
var db = await databaseFactoryIo.openDatabase('todos.db');
app
..logger = (new Logger('angel_sembast_example')..onRecord.listen(print))
..use('/api/todos', new SembastService(db, store: 'todos'))
..logger = (Logger('angel_sembast_example')..onRecord.listen(print))
..use('/api/todos', SembastService(db, store: 'todos'))
..shutdownHooks.add((_) => db.close());
var http = new AngelHttp(app);
var http = AngelHttp(app);
var server = await http.startServer('127.0.0.1', 3000);
var uri =
new Uri(scheme: 'http', host: server.address.address, port: server.port);
Uri(scheme: 'http', host: server.address.address, port: server.port);
print('angel_sembast example listening at $uri');
}

View file

@ -4,7 +4,7 @@ import 'package:sembast/sembast.dart';
class SembastService extends Service<String, Map<String, dynamic>> {
final Database database;
final Store store;
final StoreRef<int, Map<String, dynamic>> store;
/// If set to `true`, clients can remove all items by passing a `null` `id` to `remove`.
///
@ -16,12 +16,11 @@ class SembastService extends Service<String, Map<String, dynamic>> {
SembastService(this.database,
{String store, this.allowRemoveAll = false, this.allowQuery = true})
: this.store =
(store == null ? database.mainStore : database.getStore(store)),
: this.store = intMapStoreFactory.store(store),
super();
Finder _makeQuery([Map<String, dynamic> params]) {
params = new Map<String, dynamic>.from(params ?? {});
params = Map<String, dynamic>.from(params ?? {});
Filter out;
var sort = <SortOrder>[];
@ -36,16 +35,16 @@ class SembastService extends Service<String, Map<String, dynamic>> {
var v = params[key];
if (v is! Map) {
sort.add(new SortOrder(v.toString(), true));
sort.add(SortOrder(v.toString(), true));
} else {
var m = v as Map;
m.forEach((k, sorter) {
if (sorter is SortOrder) {
sort.add(sorter);
} else if (sorter is String) {
sort.add(new SortOrder(k.toString(), sorter == "-1"));
sort.add(SortOrder(k.toString(), sorter == "-1"));
} else if (sorter is num) {
sort.add(new SortOrder(k.toString(), sorter == -1));
sort.add(SortOrder(k.toString(), sorter == -1));
}
});
}
@ -57,94 +56,81 @@ class SembastService extends Service<String, Map<String, dynamic>> {
queryObj.forEach((k, v) {
if (k != 'provider' &&
!const ['__requestctx', '__responsectx'].contains(k)) {
var filter = new Filter.equal(k.toString(), v);
if (out == null)
var filter = Filter.equals(k.toString(), v);
if (out == null) {
out = filter;
else
out = new Filter.or([out, filter]);
} else {
out = Filter.or([out, filter]);
}
}
});
}
}
}
return new Finder(filter: out, sortOrders: sort);
return Finder(filter: out, sortOrders: sort);
}
Map<String, dynamic> _jsonify(Record record) {
return new Map<String, dynamic>.from(record.value as Map)
..['id'] = record.key.toString();
}
Map<String, dynamic> _withId(Map<String, dynamic> data, String id) =>
Map<String, dynamic>.from(data ?? {})..['id'] = id;
@override
Future<Map<String, dynamic>> findOne(
[Map<String, dynamic> params,
String errorMessage = 'No record was found matching the given query.']) {
return store.findRecord(_makeQuery(params)).then(_jsonify);
String errorMessage =
'No record was found matching the given query.']) async {
return (await store.findFirst(database, finder: _makeQuery(params)))?.value;
}
@override
Future<List<Map<String, dynamic>>> index(
[Map<String, dynamic> params]) async {
var records = await store.findRecords(_makeQuery(params));
return records.where((r) => r.value != null).map(_jsonify).toList();
var records = await store.find(database, finder: _makeQuery(params));
return records
.where((r) => r.value != null)
.map((r) => _withId(r.value, r.key.toString()))
.toList();
}
@override
Future<Map<String, dynamic>> read(String id,
[Map<String, dynamic> params]) async {
var record = await store.get(int.parse(id));
var record = await store.record(int.parse(id)).getSnapshot(database);
if (record == null) {
throw new AngelHttpException.notFound(
message: 'No record found for ID $id');
throw AngelHttpException.notFound(message: 'No record found for ID $id');
}
return (record as Map<String, dynamic>)..['id'] = id;
return _withId(record.value, id);
}
@override
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
[Map<String, dynamic> params]) async {
return await database.transaction((txn) async {
var store = txn.getStore(this.store.name);
var key = await store.put(data) as int;
var key = await store.add(txn, data);
var id = key.toString();
data = new Map<String, dynamic>.from(data)..['id'] = id;
return data;
return _withId(data, id);
});
}
@override
Future<Map<String, dynamic>> modify(String id, Map<String, dynamic> data,
[Map<String, dynamic> params]) async {
data = new Map<String, dynamic>.from(data)..['id'] = id;
return await database.transaction((txn) async {
var store = txn.getStore(this.store.name);
var existing = await store.get(int.parse(id));
data =
new Map<String, dynamic>.from(existing as Map<String, dynamic> ?? {})
..addAll(data)
..['id'] = id;
await store.put(data, int.parse(id));
return (await store.get(int.parse(id)) as Map<String, dynamic>)
..['id'] = id;
var record = store.record(int.parse(id));
data = await record.put(txn, data, merge: true);
return _withId(data, id);
});
}
@override
Future<Map<String, dynamic>> update(String id, Map<String, dynamic> data,
[Map<String, dynamic> params]) async {
data = new Map<String, dynamic>.from(data)..['id'] = id;
return await database.transaction((txn) async {
var store = txn.getStore(this.store.name);
await store.put(data, int.parse(id));
return (await store.get(int.parse(id)) as Map<String, dynamic>)
..['id'] = id;
var record = store.record(int.parse(id));
data = await record.put(txn, data);
return _withId(data, id);
});
}
@ -158,23 +144,23 @@ class SembastService extends Service<String, Map<String, dynamic>> {
throw AngelHttpException.forbidden(
message: 'Clients are not allowed to delete all items.');
} else {
await store.deleteAll(await store.findKeys(new Finder()));
await store.delete(database);
return {};
}
}
return database.transaction((txn) async {
var store = txn.getStore(this.store.name);
var record = await store.get(int.parse(id)) as Map<String, dynamic>;
var record = store.record(int.parse(id));
var snapshot = await record.getSnapshot(txn);
if (record == null) {
throw new AngelHttpException.notFound(
if (snapshot == null) {
throw AngelHttpException.notFound(
message: 'No record found for ID $id');
} else {
await store.delete(id);
await record.delete(txn);
}
return record..['id'] = id;
return _withId(snapshot.value, id);
});
}
}

View file

@ -4,10 +4,10 @@ homepage: https://github.com/angel-dart/sembast
version: 1.0.1
author: Tobe O <thosakwe@gmail.com>
environment:
sdk: ">=2.0.0-dev <3.0.0"
sdk: ">=2.1.0-dev <3.0.0"
dependencies:
angel_framework: ^2.0.0-alpha
sembast: ^1.9.5
sembast: ^1.19.0-dev.2
dev_dependencies:
angel_http_exception: ^1.0.0
logging:

View file

@ -12,7 +12,7 @@ main() async {
setUp(() async {
database = await memoryDatabaseFactory.openDatabase('test.db');
service = new SembastService(database);
service = SembastService(database);
});
tearDown(() => database.close());
@ -37,7 +37,7 @@ main() async {
});
test('read', () async {
var name = 'poobah${new DateTime.now().millisecondsSinceEpoch}';
var name = 'poobah${DateTime.now().millisecondsSinceEpoch}';
var input = await service.create({'name': name, 'bar': 'baz'});
print(input);
expect(await service.read(input['id'] as String), input);
@ -47,8 +47,8 @@ main() async {
var input = await service.create({'bar': 'baz', 'yes': 'no'});
var id = input['id'] as String;
var output = await service.modify(id, {'bar': 'quux'});
expect(new SplayTreeMap.from(output),
new SplayTreeMap.from({'id': id, 'bar': 'quux', 'yes': 'no'}));
expect(SplayTreeMap.from(output),
SplayTreeMap.from({'id': id, 'bar': 'quux', 'yes': 'no'}));
expect(await service.read(id), output);
});
@ -64,7 +64,7 @@ main() async {
var input = await service.create({'bar': 'baz'});
var id = input['id'] as String;
expect(await service.remove(id), input);
expect(await database.get(id), isNull);
expect(await StoreRef.main().record(id).get(database), isNull);
});
test('remove', () async {