Skip to content

Commit

Permalink
feat: add sync api for query
Browse files Browse the repository at this point in the history
  • Loading branch information
alextekartik committed Sep 13, 2024
1 parent de551bf commit 1e11304
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 132 deletions.
2 changes: 1 addition & 1 deletion app_cv_sembast/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# tekartik strict extension
include: package:tekartik_lints/strict.yaml
include: package:tekartik_lints/package.yaml
8 changes: 3 additions & 5 deletions app_cv_sembast/lib/src/app_cv_sembast.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/// Sembast cv helpers
library tekartik_app_cv_sembast;

export 'cv_query_ref.dart' show CvQueryRef, CvQueryRefExt;
export 'cv_store_ref.dart' show CvStoreRef, CvStoreRefExt;
export 'db_record.dart'
show
DbRecordListExt,
Expand All @@ -22,15 +24,11 @@ export 'db_record.dart'
CvRecordRefExt,
CvRecordRefListExt,
CvRecordsRefExt;

export 'db_store.dart'
show
CvStoreRef,
CvQueryRef,
cvIntRecordFactory,
cvStringRecordFactory,
CvStoreFactory,
CvIntStoreFactory,
CvStringStoreFactory,
CvStoreRefExt;
CvStringStoreFactory;
export 'fill_options.dart' show cvSembastFillOptions1;
63 changes: 63 additions & 0 deletions app_cv_sembast/lib/src/cv_query_ref.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:sembast/sembast.dart';

import 'db_record.dart';

/// Query ref
class CvQueryRef<K, V extends DbRecord<K>> {
/// Raw ref
final QueryRef<K, Map<String, Object?>> rawRef;

/// Constructor
CvQueryRef(this.rawRef);
}

/// Common helpers
extension CvQueryRefExt<K, V extends DbRecord<K>> on CvQueryRef<K, V> {
/// Get a single record
Future<V?> getRecord(DatabaseClient db) async {
return (await rawRef.getSnapshot(db))?.cv();
}

/// Get a single record
V? getRecordSync(DatabaseClient db) {
return rawRef.getSnapshotSync(db)?.cv();
}

/// Get all records
Future<List<V>> getRecords(DatabaseClient db) async {
return (await rawRef.getSnapshots(db)).cv();
}

/// Get all records
List<V> getRecordsSync(DatabaseClient db) {
return rawRef.getSnapshotsSync(db).cv();
}

/// Track changes
Stream<V?> onRecord(Database db) =>
rawRef.onSnapshot(db).map((snapshot) => snapshot?.cv<V>());

/// Track changes
Stream<List<V>> onRecords(Database db) =>
rawRef.onSnapshots(db).map((snapshots) => snapshots.cv<V>());

/// Track changes, first event is emitted synchronously
Stream<V?> onRecordSync(Database db) =>
rawRef.onSnapshotSync(db).map((snapshot) => snapshot?.cv<V>());

/// Track changes, first event is emitted synchronously
Stream<List<V>> onRecordsSync(Database db) =>
rawRef.onSnapshotsSync(db).map((snapshots) => snapshots.cv<V>());

/// Count
Future<int> count(DatabaseClient db) => rawRef.count(db);

/// Count sync
int countSync(DatabaseClient db) => rawRef.countSync(db);

/// onCount
Stream<int> onCount(Database db) => rawRef.onCount(db);

/// onCountSync
Stream<int> onCountSync(Database db) => rawRef.onCountSync(db);
}
84 changes: 84 additions & 0 deletions app_cv_sembast/lib/src/cv_store_ref.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import 'package:sembast/sembast.dart';

import 'cv_query_ref.dart';
import 'db_record.dart';

var _mainStore = intMapStoreFactory.store().name;

/// Store helper
class CvStoreRef<K, V extends DbRecord<K>> {
/// Raw ref
final StoreRef<K, Map<String, Object?>> rawRef;

/// Constructor
CvStoreRef(String name) : rawRef = StoreRef<K, Map<String, Object?>>(name);

/// A pointer to the main store
factory CvStoreRef.main() => CvStoreRef<K, V>(_mainStore);

@override
String toString() => 'CvStoreRef($name)';

@override
int get hashCode => name.hashCode;

@override
bool operator ==(Object other) {
if (other is CvStoreRef) {
if (other.name != name) {
return false;
}
return true;
}
return false;
}
}

/// Common helpers
extension CvStoreRefExt<K, V extends DbRecord<K>> on CvStoreRef<K, V> {
/// Name
String get name => rawRef.name;

/// Record ref
CvRecordRef<K, V> record(K key) => CvRecordRef<K, V>(this, key);

/// Records
CvRecordsRef<K, V> records(Iterable<K> keys) =>
CvRecordsRef<K, V>(this, keys);

/// Query
CvQueryRef<K, V> query({Finder? finder}) =>
CvQueryRef<K, V>(rawRef.query(finder: finder));

/// Find
Future<List<V>> find(DatabaseClient db, {Finder? finder}) =>
query(finder: finder).getRecords(db);

/// Find first
Future<V?> findFirst(DatabaseClient db, {Finder? finder}) =>
query(finder: finder).getRecord(db);

/// Add
Future<V> add(DatabaseClient db, V record) async {
var key = await rawRef.add(db, record.toMap());
record.rawRef = rawRef.record(key);
return record;
}

/// Delete
Future<int> delete(DatabaseClient db, {Finder? finder}) async {
var count = await rawRef.delete(db, finder: finder);
return count;
}

/// Cast if needed
CvStoreRef<RK, RV> cast<RK, RV extends DbRecord<RK>>() {
if (this is CvStoreRef<RK, RV>) {
return this as CvStoreRef<RK, RV>;
}
return CvStoreRef<RK, RV>(name);
}

/// Cast if needed
CvStoreRef<K, RV> castV<RV extends DbRecord<K>>() => cast<K, RV>();
}
49 changes: 41 additions & 8 deletions app_cv_sembast/lib/src/db_record.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:cv/cv.dart';
import 'package:sembast/sembast.dart';
import 'package:tekartik_app_cv_sembast/src/logger_utils.dart';

import 'db_store.dart';
import 'cv_store_ref.dart';

mixin _WithRef<K> {
RecordRef<K, Map<String, Object?>> get rawRef => _ref!;
Expand All @@ -22,22 +22,30 @@ mixin _WithRef<K> {
set id(K id) => rawRef = rawRef.store.record(id);
}

/// DbRecord
abstract class DbRecord<K> extends CvModelBase with _WithRef<K> {
/// Put(add/update) inner data
Future<void> put(DatabaseClient db, {bool merge});

/// Update inner data.
Future<bool> update(DatabaseClient db);

/// Add data.
Future<bool> add(DatabaseClient db);

/// Delete data.
Future<bool> delete(DatabaseClient db);
}

/// Access to ref.
extension DbRecordToRefExt<K> on DbRecord<K> {
/// Get the record ref
CvRecordRef<K, DbRecord<K>> get ref =>
CvStoreRef<K, DbRecord<K>>(rawRef.store.name).record(rawRef.key);
}

/// Base record implementation. Protected fields:
/// - ref
abstract class DbRecordBase<K> extends CvModelBase
with _WithRef<K>
implements DbRecord<K> {
Expand Down Expand Up @@ -106,6 +114,7 @@ class DbRecordMap<K> extends DbRecordBase<K> {
@override
List<CvField> get fields => _mapModel.fields;

/// Copy from another map
void fromModel(Map map, {List<String>? columns}) {
_mapModel = CvMapModel()..fromMap(map, columns: columns);
}
Expand Down Expand Up @@ -144,11 +153,13 @@ extension CvSembastRecordSnapshotStreamExt<K>

/// Easy extension
extension DbRecordExt<K, V> on DbRecord<K> {
/// put
Future<void> put(DatabaseClient db, {bool merge = false}) async {
var data = await rawRef.put(db, toMap(), merge: merge);
fromMap(data);
}

/// delete
Future<void> delete(DatabaseClient db) async {
await rawRef.delete(db);
}
Expand All @@ -160,7 +171,9 @@ extension DbRecordExt<K, V> on DbRecord<K> {
}*/
}

/// transaction helper
extension DatabaseClientSembastExt on DatabaseClient {
/// Transaction helper
Future<T> transaction<T>(
Future<T> Function(Transaction transaction) action) async {
var dbOrTxn = this;
Expand All @@ -174,6 +187,7 @@ extension DatabaseClientSembastExt on DatabaseClient {

/// Easy extension
extension DbRecordListExt<K, V> on List<DbRecord<K>> {
/// put
Future<void> put(DatabaseClient db, {bool merge = false}) async {
await db.transaction((txn) async {
for (var record in this) {
Expand All @@ -182,6 +196,7 @@ extension DbRecordListExt<K, V> on List<DbRecord<K>> {
});
}

/// delete
Future<int> delete(DatabaseClient db) {
return db.transaction((txn) async {
var count = 0;
Expand All @@ -201,12 +216,18 @@ extension DbRecordListExt<K, V> on List<DbRecord<K>> {
}*/
}

/// Record reference
class CvRecordRef<K, V extends DbRecord<K>> {
/// Store
final CvStoreRef<K, V> store;

/// Raw ref
final RecordRef<K, Map<String, Object?>> rawRef;

/// Key
K get key => rawRef.key;

/// Constructor
CvRecordRef(this.store, K key) : rawRef = store.rawRef.record(key);

/// To build for write
Expand All @@ -227,6 +248,7 @@ class CvRecordRef<K, V extends DbRecord<K>> {
Stream<V?> onRecordSync(Database db) =>
rawRef.onSnapshotSync(db).map((event) => event?.cv<V>());

/// Delete
Future<void> delete(DatabaseClient client) async {
await rawRef.delete(client);
}
Expand Down Expand Up @@ -264,34 +286,45 @@ class CvRecordRef<K, V extends DbRecord<K>> {

/// Records helpers
class CvRecordsRef<K, V extends DbRecord<K>> {
/// Store
final CvStoreRef<K, V> store;
final RecordsRef<K, Model> rawRef;

List<K> get keys => rawRef.keys;
/// Raw ref
final RecordsRef<K, Model> rawRefs;

/// Raw ref
@Deprecated('Use rawRefs')
RecordsRef<K, Model> get rawRef => rawRefs;

/// Keys
List<K> get keys => rawRefs.keys;

/// Record refs
List<CvRecordRef<K, V>> get refs =>
keys.map((key) => store.record(key)).toList();

/// Direct access to a record ref.
CvRecordRef<K, V> operator [](int i) => store.record(keys[i]);

/// Constructor
CvRecordsRef(this.store, Iterable<K> keys)
: rawRef = store.rawRef.records(keys);
: rawRefs = store.rawRef.records(keys);

/// Get
Future<List<V?>> get(DatabaseClient db) async =>
(await rawRef.getSnapshots(db)).cvOrNull<V>();
(await rawRefs.getSnapshots(db)).cvOrNull<V>();

/// Get synchronously
List<V?> getSync(DatabaseClient db) =>
rawRef.getSnapshotsSync(db).cvOrNull<V>();
rawRefs.getSnapshotsSync(db).cvOrNull<V>();

/// Track changes
Stream<List<V?>> onRecords(Database db) =>
rawRef.onSnapshots(db).map((event) => event.cvOrNull<V>());
rawRefs.onSnapshots(db).map((event) => event.cvOrNull<V>());

/// Delete
Future<void> delete(DatabaseClient client) async {
await rawRef.delete(client);
await rawRefs.delete(client);
}

@override
Expand Down
Loading

0 comments on commit 1e11304

Please sign in to comment.