Commit 321e602

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-03-28 23:12:36
hide repository constructors from public api
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 66522a9
health_data_store/lib/src/repositories/blood_pressure_repository.dart
@@ -0,0 +1,9 @@
+import 'package:health_data_store/src/database_manager.dart';
+import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/types/blood_pressure_record.dart';
+
+/// Repository for [BloodPressureRecord]s.
+/// 
+/// Provides high level access on [BloodPressureRecord]s saved in a 
+/// [DatabaseManager] managed database. Allows to store and query records.
+abstract class BloodPressureRepository extends Repository<BloodPressureRecord>{}
health_data_store/lib/src/repositories/blood_pressure_repository_impl.dart
@@ -1,17 +1,18 @@
-import 'package:health_data_store/health_data_store.dart';
 import 'package:health_data_store/src/database_helper.dart';
 import 'package:health_data_store/src/database_manager.dart';
 import 'package:health_data_store/src/extensions/datetime_seconds.dart';
-import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/repositories/blood_pressure_repository.dart';
+import 'package:health_data_store/src/types/blood_pressure_record.dart';
+import 'package:health_data_store/src/types/date_range.dart';
 import 'package:sqflite_common/sqflite.dart';
 
-/// Repository for [BloodPressureRecord]s.
+/// Implementation of repository for [BloodPressureRecord]s.
 /// 
 /// Provides high level access on [BloodPressureRecord]s saved in a 
 /// [DatabaseManager] managed database. Allows to store and query records.
-class BloodPressureRepository extends Repository<BloodPressureRecord> {
+class BloodPressureRepositoryImpl extends BloodPressureRepository {
   /// Create [BloodPressureRecord] repository.
-  BloodPressureRepository(this._db);
+  BloodPressureRepositoryImpl(this._db);
 
   /// The [DatabaseManager] managed database
   final Database _db;
health_data_store/lib/src/repositories/medicine_intake_repository.dart
@@ -0,0 +1,9 @@
+import 'package:health_data_store/src/database_manager.dart';
+import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/types/medicine_intake.dart';
+
+/// Repository for [MedicineIntake]s.
+///
+/// Provides high level access on intakes saved in a [DatabaseManager] managed
+/// database.
+abstract class MedicineIntakeRepository extends Repository<MedicineIntake> {}
health_data_store/lib/src/repositories/medicine_intake_repository_impl.dart
@@ -1,17 +1,19 @@
-import 'package:health_data_store/health_data_store.dart';
 import 'package:health_data_store/src/database_helper.dart';
 import 'package:health_data_store/src/database_manager.dart';
 import 'package:health_data_store/src/extensions/datetime_seconds.dart';
-import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/repositories/medicine_intake_repository.dart';
+import 'package:health_data_store/src/types/date_range.dart';
+import 'package:health_data_store/src/types/medicine.dart';
+import 'package:health_data_store/src/types/medicine_intake.dart';
 import 'package:sqflite_common/sqflite.dart';
 
-/// Repository for [MedicineIntake]s.
+/// Implementation of a repository for [MedicineIntake]s.
 ///
 /// Provides high level access on intakes saved in a [DatabaseManager] managed
 /// database.
-class MedicineIntakeRepository extends Repository<MedicineIntake> {
+class MedicineIntakeRepositoryImpl extends MedicineIntakeRepository {
   /// Create a repository for medicine intakes.
-  MedicineIntakeRepository(this._db);
+  MedicineIntakeRepositoryImpl(this._db);
 
   /// The [DatabaseManager] managed database.
   final Database _db;
health_data_store/lib/src/repositories/medicine_repository.dart
@@ -0,0 +1,20 @@
+import 'package:health_data_store/src/types/medicine.dart';
+import 'package:health_data_store/src/types/medicine_intake.dart';
+
+/// Repository for medicines that are taken by the user.
+abstract class MedicineRepository {
+
+  /// Store a [Medicine] in the repository.
+  Future<void> add(Medicine medicine);
+
+  /// Get a list of all stored Medicines that haven't been marked as removed.
+  Future<List<Medicine>> getAll();
+
+  /// Mark a medicine as deleted.
+  ///
+  /// Intakes will be deleted as soon as there is no [MedicineIntake]s
+  /// referencing them. They need to be stored to allow intakes of them to be
+  /// still displayed correctly.
+  Future<void> remove(Medicine value);
+
+}
health_data_store/lib/src/repositories/medicine_repository_impl.dart
@@ -1,18 +1,18 @@
 import 'package:health_data_store/src/database_manager.dart';
 import 'package:health_data_store/src/extensions/castable.dart';
+import 'package:health_data_store/src/repositories/medicine_repository.dart';
 import 'package:health_data_store/src/types/medicine.dart';
-import 'package:health_data_store/src/types/medicine_intake.dart';
 import 'package:sqflite_common/sqflite.dart';
 
-/// Repository for medicines that are taken by the user.
-class MedicineRepository {
+/// Implementation of repository for medicines that are taken by the user.
+class MedicineRepositoryImpl extends MedicineRepository {
   /// Create the medicine repository.
-  MedicineRepository(this._db);
+  MedicineRepositoryImpl(this._db);
 
   /// The [DatabaseManager] managed database.
   final Database _db;
 
-  /// Store a [Medicine] in the repository.
+  @override
   Future<void> add(Medicine medicine) => _db.transaction((txn) async {
     final idRes = await txn.query('Medicine', columns: ['MAX(medID)']);
     final id = (idRes.firstOrNull?['MAX(medID)']?.castOrNull<int>() ?? 0) + 1;
@@ -25,7 +25,7 @@ class MedicineRepository {
     });
   });
 
-  /// Get a list of all stored Medicines that haven't been marked as removed.
+  @override
   Future<List<Medicine>> getAll() async {
     final medData = await _db.query('Medicine',
       columns: ['designation', 'defaultDose', 'color'],
@@ -43,11 +43,7 @@ class MedicineRepository {
     return meds;
   }
 
-  /// Mark a medicine as deleted.
-  ///
-  /// Intakes will be deleted as soon as there is no [MedicineIntake]s
-  /// referencing them. They need to be stored to allow intakes of them to be
-  /// still displayed correctly.
+  @override
   Future<void> remove(Medicine value) => _db.update('Medicine', {
       'removed': 1,
     },
health_data_store/lib/src/repositories/note_repository.dart
@@ -0,0 +1,6 @@
+import 'package:health_data_store/src/database_manager.dart';
+import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/types/note.dart';
+
+/// Repository for accessing [Note]s stored in a [DatabaseManager] managed db.
+abstract class NoteRepository extends Repository<Note> {}
health_data_store/lib/src/repositories/note_repository_impl.dart
@@ -1,16 +1,16 @@
-
 import 'package:health_data_store/src/database_helper.dart';
 import 'package:health_data_store/src/database_manager.dart';
 import 'package:health_data_store/src/extensions/datetime_seconds.dart';
-import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:health_data_store/src/repositories/note_repository.dart';
 import 'package:health_data_store/src/types/date_range.dart';
 import 'package:health_data_store/src/types/note.dart';
 import 'package:sqflite_common/sqflite.dart';
 
-/// Repository for accessing [Note]s stored in a [DatabaseManager] managed db.
-class NoteRepository extends Repository<Note> {
+/// Implementation of repository for accessing [Note]s stored in a
+/// [DatabaseManager] managed db.
+class NoteRepositoryImpl extends NoteRepository {
   /// Create a repository for notes.
-  NoteRepository(this._db);
+  NoteRepositoryImpl(this._db);
 
   /// The [DatabaseManager] managed database.
   final Database _db;
health_data_store/lib/src/repositories/repository.dart
@@ -5,6 +5,9 @@ import 'package:health_data_store/src/types/date_range.dart';
 ///
 /// Repositories wrap the primitive values of DB fields into more complex
 /// types and provides domain models for the application.
+///
+/// The wrapping of an abstract class and an implementation class is necessary
+/// to avoid exposing the constructor to the public api.
 abstract class Repository<T> {
   /// Adds a new value to the repository.
   Future<void> add(T value);
health_data_store/lib/src/health_data_store.dart
@@ -1,7 +1,11 @@
 import 'package:health_data_store/src/database_manager.dart';
+import 'package:health_data_store/src/repositories/blood_pressure_repository.dart';
 import 'package:health_data_store/src/repositories/blood_pressure_repository_impl.dart';
+import 'package:health_data_store/src/repositories/medicine_intake_repository.dart';
 import 'package:health_data_store/src/repositories/medicine_intake_repository_impl.dart';
+import 'package:health_data_store/src/repositories/medicine_repository.dart';
 import 'package:health_data_store/src/repositories/medicine_repository_impl.dart';
+import 'package:health_data_store/src/repositories/note_repository.dart';
 import 'package:health_data_store/src/repositories/note_repository_impl.dart';
 import 'package:sqflite_common/sqflite.dart';
 
@@ -27,20 +31,19 @@ class HealthDataStore {
 
   /// Repository for blood pressure data.
   BloodPressureRepository get bpRepo =>
-    BloodPressureRepository(_dbMngr.db);
+    BloodPressureRepositoryImpl(_dbMngr.db);
 
   /// Repository for notes.
   NoteRepository get noteRepo =>
-    NoteRepository(_dbMngr.db);
+    NoteRepositoryImpl(_dbMngr.db);
 
   /// Repository for medicines.
   MedicineRepository get medRepo =>
-    MedicineRepository(_dbMngr.db);
+    MedicineRepositoryImpl(_dbMngr.db);
 
   /// Repository for intakes.
   MedicineIntakeRepository get intakeRepo =>
-    MedicineIntakeRepository(_dbMngr.db);
+    MedicineIntakeRepositoryImpl(_dbMngr.db);
 
-  // TODO: hide constructors
   // TODO: test
 }
health_data_store/lib/health_data_store.dart
@@ -2,10 +2,12 @@
 library; // TODO: doc more
 
 export 'src/health_data_store.dart';
-export 'src/repositories/blood_pressure_repository_impl.dart';
-export 'src/repositories/medicine_intake_repository_impl.dart';
-export 'src/repositories/medicine_repository_impl.dart';
-export 'src/repositories/note_repository_impl.dart';
+// repositories
+export 'src/repositories/blood_pressure_repository.dart';
+export 'src/repositories/medicine_intake_repository.dart';
+export 'src/repositories/medicine_repository.dart';
+export 'src/repositories/note_repository.dart';
+// types
 export 'src/types/blood_pressure_record.dart';
 export 'src/types/date_range.dart';
 export 'src/types/medicine.dart';
health_data_store/test/src/repositories/blood_pressure_repository_test.dart
@@ -1,5 +1,5 @@
-
-import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/repositories/blood_pressure_repository_impl.dart';
+import 'package:health_data_store/src/types/date_range.dart';
 import 'package:test/test.dart';
 
 import '../database_manager_test.dart';
@@ -10,12 +10,12 @@ void main() {
   test('should initialize', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    BloodPressureRepository(db.db);
+    BloodPressureRepositoryImpl(db.db);
   });
   test('should store records without errors', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     await repo.add(mockRecord(sys: 123, dia: 456, pul: 789));
     await repo.add(mockRecord(sys: 123, pul: 789));
     await repo.add(mockRecord(sys: 123));
@@ -24,7 +24,7 @@ void main() {
   test('should return stored records', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 50000, sys: 123);
     final r2 = mockRecord(time: 80000, sys: 456, dia: 457, pul: 458);
     final r3 = mockRecord(time: 20000, sys: 788, pul: 789);
@@ -42,7 +42,7 @@ void main() {
   test('should remove records', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 10000, sys: 456, dia: 457, pul: 458);
     await repo.add(r1);
 
@@ -63,7 +63,7 @@ void main() {
   test('should remove partial records', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 10000, sys: 456, dia: 457, pul: 458);
     final r2 = mockRecord(time: 20000, sys: 123);
     final r3 = mockRecord(time: 30000, sys: 788, pul: 789);
@@ -104,7 +104,7 @@ void main() {
   test('should remove correct record when multiple are at same time', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 10000, sys: 456, dia: 457, pul: 458);
     final r2 = mockRecord(time: 10000, sys: 678, dia: 457, pul: 458);
     await repo.add(r1);
@@ -121,7 +121,7 @@ void main() {
   test('should not throw when removing non existent record', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = BloodPressureRepository(db.db);
+    final repo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 10000, sys: 456, dia: 457, pul: 458);
 
     await repo.remove(r1);
health_data_store/test/src/repositories/medicine_intake_repository_test.dart
@@ -1,5 +1,6 @@
-
-import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/repositories/medicine_intake_repository_impl.dart';
+import 'package:health_data_store/src/repositories/medicine_repository_impl.dart';
+import 'package:health_data_store/src/types/date_range.dart';
 import 'package:test/test.dart';
 
 import '../database_manager_test.dart';
@@ -11,18 +12,18 @@ void main() {
   test('should initialize', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    MedicineIntakeRepository(db.db);
+    MedicineIntakeRepositoryImpl(db.db);
   });
   test('should store intakes without errors', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
     final med1 = mockMedicine(designation: 'med1', dosis: 2.4);
     final med2 = mockMedicine(designation: 'med2',);
-    final medRepo = MedicineRepository(db.db);
+    final medRepo = MedicineRepositoryImpl(db.db);
     await medRepo.add(med1);
     await medRepo.add(med2);
 
-    final repo = MedicineIntakeRepository(db.db);
+    final repo = MedicineIntakeRepositoryImpl(db.db);
     await repo.add(mockIntake(med1));
     await repo.add(mockIntake(med2));
     await repo.add(mockIntake(med1, dosis: 123));
@@ -35,11 +36,11 @@ void main() {
     addTearDown(db.close);
     final med1 = mockMedicine(dosis: 2.4);
     final med2 = mockMedicine();
-    final medRepo = MedicineRepository(db.db);
+    final medRepo = MedicineRepositoryImpl(db.db);
     await medRepo.add(med1);
     await medRepo.add(med2);
 
-    final repo = MedicineIntakeRepository(db.db);
+    final repo = MedicineIntakeRepositoryImpl(db.db);
     final t1 = mockIntake(med1, time: 20000);
     final t2 = mockIntake(med2, time: 76000);
     final t3 = mockIntake(med1, dosis: 123, time: 50000,);
@@ -58,10 +59,10 @@ void main() {
   test('should remove intakes', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final medRepo = MedicineRepository(db.db);
+    final medRepo = MedicineRepositoryImpl(db.db);
     final med = mockMedicine();
     await medRepo.add(med);
-    final repo = MedicineIntakeRepository(db.db);
+    final repo = MedicineIntakeRepositoryImpl(db.db);
     final i1 = mockIntake(med, time: 5000);
     await repo.add(i1);
 
@@ -82,8 +83,8 @@ void main() {
   test('should remove correct intake when multiple are at same time', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = MedicineIntakeRepository(db.db);
-    final medRepo = MedicineRepository(db.db);
+    final repo = MedicineIntakeRepositoryImpl(db.db);
+    final medRepo = MedicineRepositoryImpl(db.db);
     final med = mockMedicine();
     await medRepo.add(med);
     final i1 = mockIntake(med, time: 10000);
@@ -102,10 +103,10 @@ void main() {
   test('should not throw when removing non existent record', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final medRepo = MedicineRepository(db.db);
+    final medRepo = MedicineRepositoryImpl(db.db);
     final med = mockMedicine();
     await medRepo.add(med);
-    final repo = MedicineIntakeRepository(db.db);
+    final repo = MedicineIntakeRepositoryImpl(db.db);
     final i1 = mockIntake(med);
 
     await repo.remove(i1);
health_data_store/test/src/repositories/medicine_repository_test.dart
@@ -1,4 +1,5 @@
-import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/repositories/medicine_repository_impl.dart';
+import 'package:health_data_store/src/types/medicine.dart';
 import 'package:test/expect.dart';
 import 'package:test/scaffolding.dart';
 
@@ -9,19 +10,19 @@ void main() {
   test('should initialize', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    MedicineRepository(db.db);
+    MedicineRepositoryImpl(db.db);
   });
   test('should return no medicines when no are added', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = MedicineRepository(db.db);
+    final repo = MedicineRepositoryImpl(db.db);
     final all = await repo.getAll();
     expect(all, isEmpty);
   });
   test('should store all complete medicines', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = MedicineRepository(db.db);
+    final repo = MedicineRepositoryImpl(db.db);
     await repo.add(Medicine(designation: 'med1', color: 0xFF226A, dosis: 42));
     await repo.add(Medicine(designation: 'med2', color: 0xAF226B, dosis: 43));
     final all = await repo.getAll();
@@ -40,7 +41,7 @@ void main() {
   test('should store all incomplete medicines', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = MedicineRepository(db.db);
+    final repo = MedicineRepositoryImpl(db.db);
     await repo.add(Medicine(designation: 'med1', color: 0xFF226A,));
     await repo.add(Medicine(designation: 'med2', dosis: 43));
     await repo.add(Medicine(designation: 'med3',));
@@ -64,7 +65,7 @@ void main() {
   test('should mark medicines as deleted', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = MedicineRepository(db.db);
+    final repo = MedicineRepositoryImpl(db.db);
     final med1= Medicine(designation: 'med1', color: 0xFF226A, dosis: 42);
     await repo.add(med1);
     await repo.add(Medicine(designation: 'med2', color: 0xAF226B, dosis: 43));
health_data_store/test/src/repositories/note_repository_test.dart
@@ -13,12 +13,12 @@ void main() {
   test('should initialize', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    NoteRepository(db.db);
+    NoteRepositoryImpl(db.db);
   });
   test('should store notes', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = NoteRepository(db.db);
+    final repo = NoteRepositoryImpl(db.db);
     await repo.add(mockNote(color: 0x00FF00));
     await repo.add(mockNote(note: 'test'));
     expect(() async => repo.add(mockNote()), throwsA(isA<AssertionError>()));
@@ -26,7 +26,7 @@ void main() {
   test('should return stored notes', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = NoteRepository(db.db);
+    final repo = NoteRepositoryImpl(db.db);
     final note1 = mockNote(time: 100000, color: 0x00FF00);
     await repo.add(note1);
     final note2 = mockNote(time: 700000, note: 'test');
@@ -45,7 +45,7 @@ void main() {
   test('should remove notes', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final repo = NoteRepository(db.db);
+    final repo = NoteRepositoryImpl(db.db);
     final note1 = mockNote(time: 100000, color: 0x00FF00);
     await repo.add(note1);
     final note2 = mockNote(time: 700000, note: 'test');
@@ -67,10 +67,10 @@ void main() {
   test('should not return notes when only other data is present', () async {
     final db = await mockDBManager();
     addTearDown(db.close);
-    final bpRepo = BloodPressureRepository(db.db);
+    final bpRepo = BloodPressureRepositoryImpl(db.db);
     final r1 = mockRecord(time: 200000, sys: 456, dia: 457, pul: 458);
     await bpRepo.add(r1);
-    final repo = NoteRepository(db.db);
+    final repo = NoteRepositoryImpl(db.db);
     final values = await repo.get(DateRange(
       start: DateTime.fromMillisecondsSinceEpoch(100000),
       end: DateTime.fromMillisecondsSinceEpoch(800000),
health_data_store/test/src/types/date_range_test.dart
@@ -1,4 +1,4 @@
-import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/types/date_range.dart';
 import 'package:test/test.dart';
 
 void main() {
health_data_store/test/src/health_data_store_test.dart
@@ -1,7 +1,16 @@
-// ignore_for_file: prefer_const_constructors
+import 'package:health_data_store/health_data_store.dart';
+import 'package:sqflite_common/sqflite.dart';
+import 'package:test/expect.dart';
+import 'package:test/scaffolding.dart';
 
+import 'database_manager_test.dart';
 
 void main() {
- // TODO: implement
- throw UnimplementedError('TODO');
+ sqfliteTestInit();
+ test('should initialize with new db', () async {
+  final store = await HealthDataStore.load(
+    await openDatabase(inMemoryDatabasePath));
+  expect(store, isNotNull);
+ });
+ // TODO: implement more tests
 }