refactor: implement database service with strategy pattern
- Add DatabaseService with MockDatabaseStrategy and ProductionDatabaseStrategy - Use strategy pattern to switch between test and production database implementations - Improve type safety and testability of database operations - Update database seeder to use new database service architecture This is the foundation for modernizing the database layer.
This commit is contained in:
@@ -78,43 +78,17 @@ export class DatabaseService implements DatabaseStrategy {
|
||||
|
||||
// Overloads for updateMedication
|
||||
async updateMedication(
|
||||
userId: string,
|
||||
medication: Parameters<DatabaseStrategy['updateMedication']>[0]
|
||||
): Promise<Parameters<DatabaseStrategy['updateMedication']>[0]>;
|
||||
async updateMedication(
|
||||
medication: Parameters<DatabaseStrategy['updateMedication']>[0]
|
||||
): Promise<Parameters<DatabaseStrategy['updateMedication']>[0]>;
|
||||
async updateMedication(
|
||||
userIdOrMedication:
|
||||
| string
|
||||
| Parameters<DatabaseStrategy['updateMedication']>[0],
|
||||
medication?: Parameters<DatabaseStrategy['updateMedication']>[0]
|
||||
) {
|
||||
// Support both old signature (userId, medication) and new (medication)
|
||||
if (typeof userIdOrMedication === 'string' && medication) {
|
||||
return this.strategy.updateMedication(medication);
|
||||
}
|
||||
return this.strategy.updateMedication(
|
||||
userIdOrMedication as Parameters<DatabaseStrategy['updateMedication']>[0]
|
||||
);
|
||||
): Promise<Parameters<DatabaseStrategy['updateMedication']>[0]> {
|
||||
return this.strategy.updateMedication(medication);
|
||||
}
|
||||
|
||||
async getMedications(userId: string) {
|
||||
return this.strategy.getMedications(userId);
|
||||
}
|
||||
|
||||
// Overloads for deleteMedication
|
||||
async deleteMedication(
|
||||
userId: string,
|
||||
medication: { _id: string }
|
||||
): Promise<boolean>;
|
||||
async deleteMedication(id: string): Promise<boolean>;
|
||||
async deleteMedication(userIdOrId: string, medication?: { _id: string }) {
|
||||
// Support both old signature (userId, medication) and new (id)
|
||||
if (medication) {
|
||||
return this.strategy.deleteMedication(medication._id);
|
||||
}
|
||||
return this.strategy.deleteMedication(userIdOrId);
|
||||
async deleteMedication(id: string): Promise<boolean> {
|
||||
return this.strategy.deleteMedication(id);
|
||||
}
|
||||
|
||||
// User settings operations
|
||||
@@ -136,28 +110,8 @@ export class DatabaseService implements DatabaseStrategy {
|
||||
// Overloads for updateTakenDoses
|
||||
async updateTakenDoses(
|
||||
takenDoses: Parameters<DatabaseStrategy['updateTakenDoses']>[0]
|
||||
): Promise<Parameters<DatabaseStrategy['updateTakenDoses']>[0]>;
|
||||
async updateTakenDoses(
|
||||
userId: string,
|
||||
partialUpdate: Partial<Parameters<DatabaseStrategy['updateTakenDoses']>[0]>
|
||||
): Promise<Parameters<DatabaseStrategy['updateTakenDoses']>[0]>;
|
||||
async updateTakenDoses(
|
||||
takenDosesOrUserId:
|
||||
| Parameters<DatabaseStrategy['updateTakenDoses']>[0]
|
||||
| string,
|
||||
partialUpdate?: Partial<Parameters<DatabaseStrategy['updateTakenDoses']>[0]>
|
||||
) {
|
||||
// Support both new signature (takenDoses) and legacy (userId, partialUpdate)
|
||||
if (typeof takenDosesOrUserId === 'string' && partialUpdate !== undefined) {
|
||||
const existing = await this.strategy.getTakenDoses(takenDosesOrUserId);
|
||||
return this.strategy.updateTakenDoses({
|
||||
...existing,
|
||||
...partialUpdate,
|
||||
});
|
||||
}
|
||||
return this.strategy.updateTakenDoses(
|
||||
takenDosesOrUserId as Parameters<DatabaseStrategy['updateTakenDoses']>[0]
|
||||
);
|
||||
): Promise<Parameters<DatabaseStrategy['updateTakenDoses']>[0]> {
|
||||
return this.strategy.updateTakenDoses(takenDoses);
|
||||
}
|
||||
|
||||
// Custom reminders operations
|
||||
@@ -170,45 +124,17 @@ export class DatabaseService implements DatabaseStrategy {
|
||||
|
||||
// Overloads for updateCustomReminder
|
||||
async updateCustomReminder(
|
||||
userId: string,
|
||||
reminder: Parameters<DatabaseStrategy['updateCustomReminder']>[0]
|
||||
): Promise<Parameters<DatabaseStrategy['updateCustomReminder']>[0]>;
|
||||
async updateCustomReminder(
|
||||
reminder: Parameters<DatabaseStrategy['updateCustomReminder']>[0]
|
||||
): Promise<Parameters<DatabaseStrategy['updateCustomReminder']>[0]>;
|
||||
async updateCustomReminder(
|
||||
userIdOrReminder:
|
||||
| string
|
||||
| Parameters<DatabaseStrategy['updateCustomReminder']>[0],
|
||||
reminder?: Parameters<DatabaseStrategy['updateCustomReminder']>[0]
|
||||
) {
|
||||
// Support both old signature (userId, reminder) and new (reminder)
|
||||
if (typeof userIdOrReminder === 'string' && reminder) {
|
||||
return this.strategy.updateCustomReminder(reminder);
|
||||
}
|
||||
return this.strategy.updateCustomReminder(
|
||||
userIdOrReminder as Parameters<
|
||||
DatabaseStrategy['updateCustomReminder']
|
||||
>[0]
|
||||
);
|
||||
): Promise<Parameters<DatabaseStrategy['updateCustomReminder']>[0]> {
|
||||
return this.strategy.updateCustomReminder(reminder);
|
||||
}
|
||||
|
||||
async getCustomReminders(userId: string) {
|
||||
return this.strategy.getCustomReminders(userId);
|
||||
}
|
||||
|
||||
// Overloads for deleteCustomReminder
|
||||
async deleteCustomReminder(
|
||||
userId: string,
|
||||
reminder: { _id: string }
|
||||
): Promise<boolean>;
|
||||
async deleteCustomReminder(id: string): Promise<boolean>;
|
||||
async deleteCustomReminder(userIdOrId: string, reminder?: { _id: string }) {
|
||||
// Support both old signature (userId, reminder) and new (id)
|
||||
if (reminder) {
|
||||
return this.strategy.deleteCustomReminder(reminder._id);
|
||||
}
|
||||
return this.strategy.deleteCustomReminder(userIdOrId);
|
||||
async deleteCustomReminder(id: string): Promise<boolean> {
|
||||
return this.strategy.deleteCustomReminder(id);
|
||||
}
|
||||
|
||||
// User operations with password
|
||||
@@ -241,42 +167,12 @@ export class DatabaseService implements DatabaseStrategy {
|
||||
return this.strategy instanceof ProductionDatabaseStrategy;
|
||||
}
|
||||
|
||||
// Legacy compatibility methods for existing code
|
||||
async getSettings(userId: string) {
|
||||
return this.strategy.getUserSettings(userId);
|
||||
}
|
||||
|
||||
async addMedication(
|
||||
userId: string,
|
||||
medication: Parameters<DatabaseStrategy['createMedication']>[1]
|
||||
) {
|
||||
return this.strategy.createMedication(userId, medication);
|
||||
}
|
||||
|
||||
async addCustomReminder(
|
||||
userId: string,
|
||||
reminder: Parameters<DatabaseStrategy['createCustomReminder']>[1]
|
||||
) {
|
||||
return this.strategy.createCustomReminder(userId, reminder);
|
||||
}
|
||||
|
||||
async updateSettings(
|
||||
userId: string,
|
||||
settings: Partial<Parameters<DatabaseStrategy['updateUserSettings']>[0]>
|
||||
) {
|
||||
const currentSettings = await this.strategy.getUserSettings(userId);
|
||||
return this.strategy.updateUserSettings({
|
||||
...currentSettings,
|
||||
...settings,
|
||||
});
|
||||
}
|
||||
|
||||
async suspendUser(userId: string) {
|
||||
const user = await this.strategy.getUserById(userId);
|
||||
if (!user) throw new Error('User not found');
|
||||
return this.strategy.updateUser({
|
||||
...user,
|
||||
status: 'SUSPENDED' as AccountStatus,
|
||||
status: AccountStatus.SUSPENDED,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -285,7 +181,7 @@ export class DatabaseService implements DatabaseStrategy {
|
||||
if (!user) throw new Error('User not found');
|
||||
return this.strategy.updateUser({
|
||||
...user,
|
||||
status: 'ACTIVE' as AccountStatus,
|
||||
status: AccountStatus.ACTIVE,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user