2025-02-17 13:40:37 -05:00
|
|
|
// lib/db/services/DevSeederService.ts
|
|
|
|
import { SQLiteDatabase } from 'expo-sqlite';
|
|
|
|
import { ExerciseService } from './ExerciseService';
|
2025-03-08 15:48:07 -05:00
|
|
|
import { EventCache } from '@/lib/db/services/EventCache';
|
|
|
|
import { WorkoutService } from './WorkoutService';
|
|
|
|
import { TemplateService } from './TemplateService';
|
2025-02-17 13:40:37 -05:00
|
|
|
import { logDatabaseInfo } from '../debug';
|
|
|
|
import { mockExerciseEvents, convertNostrToExercise } from '../../mocks/exercises';
|
2025-03-08 15:48:07 -05:00
|
|
|
import { DbService } from '../db-service';
|
2025-03-06 16:34:50 -05:00
|
|
|
import NDK, { NDKEvent } from '@nostr-dev-kit/ndk-mobile';
|
2025-02-17 13:40:37 -05:00
|
|
|
|
|
|
|
export class DevSeederService {
|
|
|
|
private db: SQLiteDatabase;
|
2025-03-08 15:48:07 -05:00
|
|
|
private dbService: DbService;
|
2025-02-17 13:40:37 -05:00
|
|
|
private exerciseService: ExerciseService;
|
2025-03-08 15:48:07 -05:00
|
|
|
private workoutService: WorkoutService | null = null;
|
|
|
|
private templateService: TemplateService | null = null;
|
|
|
|
private eventCache: EventCache | null = null;
|
2025-03-06 16:34:50 -05:00
|
|
|
private ndk: NDK | null = null;
|
2025-02-17 13:40:37 -05:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
db: SQLiteDatabase,
|
2025-03-06 16:34:50 -05:00
|
|
|
exerciseService: ExerciseService
|
2025-02-17 13:40:37 -05:00
|
|
|
) {
|
|
|
|
this.db = db;
|
2025-03-08 15:48:07 -05:00
|
|
|
this.dbService = new DbService(db);
|
2025-02-17 13:40:37 -05:00
|
|
|
this.exerciseService = exerciseService;
|
2025-03-08 15:48:07 -05:00
|
|
|
|
|
|
|
// Try to initialize other services if needed
|
|
|
|
try {
|
|
|
|
this.workoutService = new WorkoutService(db);
|
|
|
|
this.templateService = new TemplateService(db);
|
|
|
|
this.eventCache = new EventCache(db);
|
|
|
|
} catch (error) {
|
|
|
|
console.log('Some services not available yet:', error);
|
|
|
|
}
|
2025-03-06 16:34:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
setNDK(ndk: NDK) {
|
|
|
|
this.ndk = ndk;
|
2025-02-17 13:40:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
async seedDatabase() {
|
|
|
|
if (!__DEV__) return;
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log('Starting development database seeding...');
|
|
|
|
|
|
|
|
// Log initial database state
|
|
|
|
await logDatabaseInfo();
|
|
|
|
|
|
|
|
// Check if we already have exercises
|
|
|
|
const existingCount = (await this.exerciseService.getAllExercises()).length;
|
|
|
|
|
|
|
|
if (existingCount > 0) {
|
|
|
|
console.log('Database already seeded with', existingCount, 'exercises');
|
2025-03-08 15:48:07 -05:00
|
|
|
} else {
|
|
|
|
// Start transaction for all seeding operations
|
|
|
|
await this.db.withTransactionAsync(async () => {
|
|
|
|
console.log('Seeding mock exercises...');
|
|
|
|
|
|
|
|
// Process all events within the same transaction
|
|
|
|
for (const eventData of mockExerciseEvents) {
|
2025-03-06 16:34:50 -05:00
|
|
|
if (this.ndk) {
|
2025-03-08 15:48:07 -05:00
|
|
|
// If NDK is available, use it to cache the event
|
|
|
|
const event = new NDKEvent(this.ndk);
|
|
|
|
Object.assign(event, eventData);
|
|
|
|
|
|
|
|
// Cache the event in NDK
|
2025-03-06 16:34:50 -05:00
|
|
|
const ndkEvent = new NDKEvent(this.ndk);
|
|
|
|
|
|
|
|
// Copy event properties
|
|
|
|
ndkEvent.kind = eventData.kind;
|
|
|
|
ndkEvent.content = eventData.content;
|
|
|
|
ndkEvent.created_at = eventData.created_at;
|
|
|
|
ndkEvent.tags = eventData.tags;
|
|
|
|
|
|
|
|
// If we have mock signatures, use them
|
|
|
|
if (eventData.sig) {
|
|
|
|
ndkEvent.sig = eventData.sig;
|
|
|
|
ndkEvent.id = eventData.id || '';
|
|
|
|
ndkEvent.pubkey = eventData.pubkey || '';
|
|
|
|
} else if (this.ndk.signer) {
|
|
|
|
// Otherwise sign if possible
|
|
|
|
await ndkEvent.sign();
|
|
|
|
}
|
|
|
|
}
|
2025-03-08 15:48:07 -05:00
|
|
|
|
|
|
|
// Cache the event if possible
|
|
|
|
if (this.eventCache) {
|
|
|
|
try {
|
|
|
|
await this.eventCache.setEvent(eventData, true);
|
|
|
|
} catch (error) {
|
|
|
|
console.log('Error caching event:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create exercise from the mock data regardless of NDK availability
|
|
|
|
const exercise = convertNostrToExercise(eventData);
|
|
|
|
await this.exerciseService.createExercise(exercise, true);
|
2025-03-06 16:34:50 -05:00
|
|
|
}
|
2025-03-08 15:48:07 -05:00
|
|
|
|
|
|
|
console.log('Successfully seeded', mockExerciseEvents.length, 'exercises');
|
|
|
|
});
|
|
|
|
}
|
2025-02-17 13:40:37 -05:00
|
|
|
|
2025-03-08 15:48:07 -05:00
|
|
|
// Seed workout and template tables
|
|
|
|
await this.seedWorkoutTables();
|
|
|
|
await this.seedTemplates();
|
2025-02-17 13:40:37 -05:00
|
|
|
|
|
|
|
// Log final database state
|
|
|
|
await logDatabaseInfo();
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error seeding database:', error);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-08 15:48:07 -05:00
|
|
|
async seedWorkoutTables() {
|
|
|
|
if (!__DEV__) return;
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log('Checking workout tables seeding...');
|
|
|
|
|
|
|
|
// Check if we already have workout data
|
|
|
|
try {
|
|
|
|
const hasWorkouts = await this.dbService.getFirstAsync<{ count: number }>(
|
|
|
|
'SELECT COUNT(*) as count FROM workouts'
|
|
|
|
);
|
|
|
|
|
|
|
|
if (hasWorkouts && hasWorkouts.count > 0) {
|
|
|
|
console.log('Workout tables already seeded with', hasWorkouts.count, 'workouts');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('No workout data found, but tables should be created');
|
|
|
|
|
|
|
|
// Optional: Add mock workout data here
|
|
|
|
// if (this.workoutService) {
|
|
|
|
// // Create mock workouts
|
|
|
|
// // await this.workoutService.saveWorkout(mockWorkout);
|
|
|
|
// }
|
|
|
|
} catch (error) {
|
|
|
|
console.log('Workout tables may not exist yet - will be created in schema update');
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error checking workout tables:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async seedTemplates() {
|
|
|
|
if (!__DEV__) return;
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log('Checking template tables seeding...');
|
|
|
|
|
|
|
|
// Check if templates table exists and has data
|
|
|
|
try {
|
|
|
|
const hasTemplates = await this.dbService.getFirstAsync<{ count: number }>(
|
|
|
|
'SELECT COUNT(*) as count FROM templates'
|
|
|
|
);
|
|
|
|
|
|
|
|
if (hasTemplates && hasTemplates.count > 0) {
|
|
|
|
console.log('Template tables already seeded with', hasTemplates.count, 'templates');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('No template data found, but tables should be created');
|
|
|
|
|
|
|
|
// Optional: Add mock template data here
|
|
|
|
// if (this.templateService) {
|
|
|
|
// // Create mock templates
|
|
|
|
// // await this.templateService.createTemplate(mockTemplate);
|
|
|
|
// }
|
|
|
|
} catch (error) {
|
|
|
|
console.log('Template tables may not exist yet - will be created in schema update');
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error checking template tables:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-17 13:40:37 -05:00
|
|
|
async clearDatabase() {
|
|
|
|
if (!__DEV__) return;
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log('Clearing development database...');
|
|
|
|
|
|
|
|
await this.db.withTransactionAsync(async () => {
|
|
|
|
const tables = [
|
2025-03-08 15:48:07 -05:00
|
|
|
// Original tables
|
2025-02-17 13:40:37 -05:00
|
|
|
'exercises',
|
|
|
|
'exercise_tags',
|
|
|
|
'nostr_events',
|
|
|
|
'event_tags',
|
2025-03-06 16:34:50 -05:00
|
|
|
'cache_metadata',
|
2025-03-08 15:48:07 -05:00
|
|
|
'ndk_cache',
|
|
|
|
|
|
|
|
// New tables
|
|
|
|
'workouts',
|
|
|
|
'workout_exercises',
|
|
|
|
'workout_sets',
|
|
|
|
'templates',
|
|
|
|
'template_exercises'
|
2025-02-17 13:40:37 -05:00
|
|
|
];
|
|
|
|
|
|
|
|
for (const table of tables) {
|
2025-03-08 15:48:07 -05:00
|
|
|
try {
|
|
|
|
await this.db.runAsync(`DELETE FROM ${table}`);
|
|
|
|
console.log(`Cleared table: ${table}`);
|
|
|
|
} catch (error) {
|
|
|
|
console.log(`Table ${table} might not exist yet, skipping`);
|
|
|
|
}
|
2025-02-17 13:40:37 -05:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log('Successfully cleared database');
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error clearing database:', error);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async resetDatabase() {
|
|
|
|
if (!__DEV__) return;
|
|
|
|
|
|
|
|
await this.clearDatabase();
|
|
|
|
await this.seedDatabase();
|
|
|
|
}
|
|
|
|
}
|