Merge pull request #2 from alextekartik/master
feat: use the new sembast store API
This commit is contained in:
commit
eda2acc36a
4 changed files with 52 additions and 66 deletions
|
@ -5,17 +5,17 @@ import 'package:logging/logging.dart';
|
||||||
import 'package:sembast/sembast_io.dart';
|
import 'package:sembast/sembast_io.dart';
|
||||||
|
|
||||||
main() async {
|
main() async {
|
||||||
var app = new Angel();
|
var app = Angel();
|
||||||
var db = await databaseFactoryIo.openDatabase('todos.db');
|
var db = await databaseFactoryIo.openDatabase('todos.db');
|
||||||
|
|
||||||
app
|
app
|
||||||
..logger = (new Logger('angel_sembast_example')..onRecord.listen(print))
|
..logger = (Logger('angel_sembast_example')..onRecord.listen(print))
|
||||||
..use('/api/todos', new SembastService(db, store: 'todos'))
|
..use('/api/todos', SembastService(db, store: 'todos'))
|
||||||
..shutdownHooks.add((_) => db.close());
|
..shutdownHooks.add((_) => db.close());
|
||||||
|
|
||||||
var http = new AngelHttp(app);
|
var http = AngelHttp(app);
|
||||||
var server = await http.startServer('127.0.0.1', 3000);
|
var server = await http.startServer('127.0.0.1', 3000);
|
||||||
var uri =
|
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');
|
print('angel_sembast example listening at $uri');
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:sembast/sembast.dart';
|
||||||
|
|
||||||
class SembastService extends Service<String, Map<String, dynamic>> {
|
class SembastService extends Service<String, Map<String, dynamic>> {
|
||||||
final Database database;
|
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`.
|
/// 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,
|
SembastService(this.database,
|
||||||
{String store, this.allowRemoveAll = false, this.allowQuery = true})
|
{String store, this.allowRemoveAll = false, this.allowQuery = true})
|
||||||
: this.store =
|
: this.store = intMapStoreFactory.store(store),
|
||||||
(store == null ? database.mainStore : database.getStore(store)),
|
|
||||||
super();
|
super();
|
||||||
|
|
||||||
Finder _makeQuery([Map<String, dynamic> params]) {
|
Finder _makeQuery([Map<String, dynamic> params]) {
|
||||||
params = new Map<String, dynamic>.from(params ?? {});
|
params = Map<String, dynamic>.from(params ?? {});
|
||||||
Filter out;
|
Filter out;
|
||||||
var sort = <SortOrder>[];
|
var sort = <SortOrder>[];
|
||||||
|
|
||||||
|
@ -36,16 +35,16 @@ class SembastService extends Service<String, Map<String, dynamic>> {
|
||||||
var v = params[key];
|
var v = params[key];
|
||||||
|
|
||||||
if (v is! Map) {
|
if (v is! Map) {
|
||||||
sort.add(new SortOrder(v.toString(), true));
|
sort.add(SortOrder(v.toString(), true));
|
||||||
} else {
|
} else {
|
||||||
var m = v as Map;
|
var m = v as Map;
|
||||||
m.forEach((k, sorter) {
|
m.forEach((k, sorter) {
|
||||||
if (sorter is SortOrder) {
|
if (sorter is SortOrder) {
|
||||||
sort.add(sorter);
|
sort.add(sorter);
|
||||||
} else if (sorter is String) {
|
} 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) {
|
} 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) {
|
queryObj.forEach((k, v) {
|
||||||
if (k != 'provider' &&
|
if (k != 'provider' &&
|
||||||
!const ['__requestctx', '__responsectx'].contains(k)) {
|
!const ['__requestctx', '__responsectx'].contains(k)) {
|
||||||
var filter = new Filter.equal(k.toString(), v);
|
var filter = Filter.equals(k.toString(), v);
|
||||||
if (out == null)
|
if (out == null) {
|
||||||
out = filter;
|
out = filter;
|
||||||
else
|
} else {
|
||||||
out = new Filter.or([out, filter]);
|
out = Filter.or([out, filter]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Finder(filter: out, sortOrders: sort);
|
return Finder(filter: out, sortOrders: sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _jsonify(Record record) {
|
Map<String, dynamic> _withId(Map<String, dynamic> data, String id) =>
|
||||||
return new Map<String, dynamic>.from(record.value as Map)
|
Map<String, dynamic>.from(data ?? {})..['id'] = id;
|
||||||
..['id'] = record.key.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> findOne(
|
Future<Map<String, dynamic>> findOne(
|
||||||
[Map<String, dynamic> params,
|
[Map<String, dynamic> params,
|
||||||
String errorMessage = 'No record was found matching the given query.']) {
|
String errorMessage =
|
||||||
return store.findRecord(_makeQuery(params)).then(_jsonify);
|
'No record was found matching the given query.']) async {
|
||||||
|
return (await store.findFirst(database, finder: _makeQuery(params)))?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Map<String, dynamic>>> index(
|
Future<List<Map<String, dynamic>>> index(
|
||||||
[Map<String, dynamic> params]) async {
|
[Map<String, dynamic> params]) async {
|
||||||
var records = await store.findRecords(_makeQuery(params));
|
var records = await store.find(database, finder: _makeQuery(params));
|
||||||
return records.where((r) => r.value != null).map(_jsonify).toList();
|
return records
|
||||||
|
.where((r) => r.value != null)
|
||||||
|
.map((r) => _withId(r.value, r.key.toString()))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> read(String id,
|
Future<Map<String, dynamic>> read(String id,
|
||||||
[Map<String, dynamic> params]) async {
|
[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) {
|
if (record == null) {
|
||||||
throw new AngelHttpException.notFound(
|
throw AngelHttpException.notFound(message: 'No record found for ID $id');
|
||||||
message: 'No record found for ID $id');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (record as Map<String, dynamic>)..['id'] = id;
|
return _withId(record.value, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
|
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
|
||||||
[Map<String, dynamic> params]) async {
|
[Map<String, dynamic> params]) async {
|
||||||
return await database.transaction((txn) async {
|
return await database.transaction((txn) async {
|
||||||
var store = txn.getStore(this.store.name);
|
var key = await store.add(txn, data);
|
||||||
var key = await store.put(data) as int;
|
|
||||||
var id = key.toString();
|
var id = key.toString();
|
||||||
data = new Map<String, dynamic>.from(data)..['id'] = id;
|
return _withId(data, id);
|
||||||
return data;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> modify(String id, Map<String, dynamic> data,
|
Future<Map<String, dynamic>> modify(String id, Map<String, dynamic> data,
|
||||||
[Map<String, dynamic> params]) async {
|
[Map<String, dynamic> params]) async {
|
||||||
data = new Map<String, dynamic>.from(data)..['id'] = id;
|
|
||||||
|
|
||||||
return await database.transaction((txn) async {
|
return await database.transaction((txn) async {
|
||||||
var store = txn.getStore(this.store.name);
|
var record = store.record(int.parse(id));
|
||||||
var existing = await store.get(int.parse(id));
|
data = await record.put(txn, data, merge: true);
|
||||||
|
return _withId(data, 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;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> update(String id, Map<String, dynamic> data,
|
Future<Map<String, dynamic>> update(String id, Map<String, dynamic> data,
|
||||||
[Map<String, dynamic> params]) async {
|
[Map<String, dynamic> params]) async {
|
||||||
data = new Map<String, dynamic>.from(data)..['id'] = id;
|
|
||||||
|
|
||||||
return await database.transaction((txn) async {
|
return await database.transaction((txn) async {
|
||||||
var store = txn.getStore(this.store.name);
|
var record = store.record(int.parse(id));
|
||||||
await store.put(data, int.parse(id));
|
data = await record.put(txn, data);
|
||||||
return (await store.get(int.parse(id)) as Map<String, dynamic>)
|
return _withId(data, id);
|
||||||
..['id'] = id;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,23 +144,23 @@ class SembastService extends Service<String, Map<String, dynamic>> {
|
||||||
throw AngelHttpException.forbidden(
|
throw AngelHttpException.forbidden(
|
||||||
message: 'Clients are not allowed to delete all items.');
|
message: 'Clients are not allowed to delete all items.');
|
||||||
} else {
|
} else {
|
||||||
await store.deleteAll(await store.findKeys(new Finder()));
|
await store.delete(database);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return database.transaction((txn) async {
|
return database.transaction((txn) async {
|
||||||
var store = txn.getStore(this.store.name);
|
var record = store.record(int.parse(id));
|
||||||
var record = await store.get(int.parse(id)) as Map<String, dynamic>;
|
var snapshot = await record.getSnapshot(txn);
|
||||||
|
|
||||||
if (record == null) {
|
if (snapshot == null) {
|
||||||
throw new AngelHttpException.notFound(
|
throw AngelHttpException.notFound(
|
||||||
message: 'No record found for ID $id');
|
message: 'No record found for ID $id');
|
||||||
} else {
|
} else {
|
||||||
await store.delete(id);
|
await record.delete(txn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return record..['id'] = id;
|
return _withId(snapshot.value, id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ homepage: https://github.com/angel-dart/sembast
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
author: Tobe O <thosakwe@gmail.com>
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.0.0-dev <3.0.0"
|
sdk: ">=2.1.0-dev <3.0.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
angel_framework: ^2.0.0-alpha
|
angel_framework: ^2.0.0-alpha
|
||||||
sembast: ^1.9.5
|
sembast: ^1.19.0-dev.2
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel_http_exception: ^1.0.0
|
angel_http_exception: ^1.0.0
|
||||||
logging:
|
logging:
|
||||||
|
|
|
@ -12,7 +12,7 @@ main() async {
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
database = await memoryDatabaseFactory.openDatabase('test.db');
|
database = await memoryDatabaseFactory.openDatabase('test.db');
|
||||||
service = new SembastService(database);
|
service = SembastService(database);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() => database.close());
|
tearDown(() => database.close());
|
||||||
|
@ -37,7 +37,7 @@ main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('read', () 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'});
|
var input = await service.create({'name': name, 'bar': 'baz'});
|
||||||
print(input);
|
print(input);
|
||||||
expect(await service.read(input['id'] as String), 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 input = await service.create({'bar': 'baz', 'yes': 'no'});
|
||||||
var id = input['id'] as String;
|
var id = input['id'] as String;
|
||||||
var output = await service.modify(id, {'bar': 'quux'});
|
var output = await service.modify(id, {'bar': 'quux'});
|
||||||
expect(new SplayTreeMap.from(output),
|
expect(SplayTreeMap.from(output),
|
||||||
new SplayTreeMap.from({'id': id, 'bar': 'quux', 'yes': 'no'}));
|
SplayTreeMap.from({'id': id, 'bar': 'quux', 'yes': 'no'}));
|
||||||
expect(await service.read(id), output);
|
expect(await service.read(id), output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ main() async {
|
||||||
var input = await service.create({'bar': 'baz'});
|
var input = await service.create({'bar': 'baz'});
|
||||||
var id = input['id'] as String;
|
var id = input['id'] as String;
|
||||||
expect(await service.remove(id), input);
|
expect(await service.remove(id), input);
|
||||||
expect(await database.get(id), isNull);
|
expect(await StoreRef.main().record(id).get(database), isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('remove', () async {
|
test('remove', () async {
|
||||||
|
|
Loading…
Reference in a new issue