mirror of
https://github.com/DocNR/POWR.git
synced 2025-06-23 16:05:31 +00:00
297 lines
9.3 KiB
TypeScript
297 lines
9.3 KiB
TypeScript
// lib/db/services/DevSeederService.ts
|
|
import { SQLiteDatabase } from 'expo-sqlite';
|
|
import { ExerciseService } from './ExerciseService';
|
|
import { EventCache } from '@/lib/db/services/EventCache';
|
|
import { WorkoutService } from './WorkoutService';
|
|
import { TemplateService } from './TemplateService';
|
|
import { logDatabaseInfo } from '../debug';
|
|
import { mockExerciseEvents, convertNostrToExercise } from '../../mocks/exercises';
|
|
import { DbService } from '../db-service';
|
|
import NDK, { NDKEvent } from '@nostr-dev-kit/ndk-mobile';
|
|
import { NostrEvent } from '@/types/nostr'; // Assuming you have this type defined
|
|
|
|
export class DevSeederService {
|
|
private db: SQLiteDatabase;
|
|
private dbService: DbService;
|
|
private exerciseService: ExerciseService;
|
|
private workoutService: WorkoutService | null = null;
|
|
private templateService: TemplateService | null = null;
|
|
private eventCache: EventCache | null = null;
|
|
private ndk: NDK | null = null;
|
|
|
|
constructor(
|
|
db: SQLiteDatabase,
|
|
exerciseService: ExerciseService
|
|
) {
|
|
this.db = db;
|
|
this.dbService = new DbService(db);
|
|
this.exerciseService = exerciseService;
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
setNDK(ndk: NDK) {
|
|
this.ndk = ndk;
|
|
}
|
|
|
|
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');
|
|
} 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) {
|
|
if (this.ndk) {
|
|
// 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
|
|
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();
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
console.log('Successfully seeded', mockExerciseEvents.length, 'exercises');
|
|
});
|
|
}
|
|
|
|
// Seed workout and template tables
|
|
await this.seedWorkoutTables();
|
|
await this.seedTemplates();
|
|
|
|
// Log final database state
|
|
await logDatabaseInfo();
|
|
|
|
} catch (error) {
|
|
console.error('Error seeding database:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Seed the database with real events from Nostr relays instead of mock data
|
|
* @param filter The filter to use when fetching events from relays
|
|
* @param limit Maximum number of events to seed (optional)
|
|
*/
|
|
async seedFromNostr(filter: any, limit?: number) {
|
|
if (!this.ndk) {
|
|
console.log('NDK not available for seeding from Nostr');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
console.log(`Seeding from Nostr with filter:`, filter);
|
|
|
|
// Fetch events from relays
|
|
const events = await this.ndk.fetchEvents(filter);
|
|
|
|
console.log(`Found ${events.size} events on Nostr`);
|
|
|
|
// Convert to array and limit if needed
|
|
const eventsArray = Array.from(events);
|
|
const eventsToProcess = limit ? eventsArray.slice(0, limit) : eventsArray;
|
|
|
|
// Process each event individually
|
|
let successCount = 0;
|
|
|
|
for (const ndkEvent of eventsToProcess) {
|
|
try {
|
|
// Convert NDKEvent to your NostrEvent format
|
|
const nostrEvent: NostrEvent = {
|
|
id: ndkEvent.id || '',
|
|
pubkey: ndkEvent.pubkey || '',
|
|
created_at: ndkEvent.created_at || 0, // Set a default value of 0 if undefined
|
|
kind: ndkEvent.kind || 0,
|
|
tags: ndkEvent.tags || [],
|
|
content: ndkEvent.content || '',
|
|
sig: ndkEvent.sig || ''
|
|
};
|
|
|
|
// Cache the event
|
|
if (this.eventCache) {
|
|
await this.eventCache.setEvent(nostrEvent, true);
|
|
}
|
|
|
|
// Process based on kind
|
|
if (ndkEvent.kind === 33401) { // Exercise
|
|
const exercise = convertNostrToExercise(nostrEvent);
|
|
await this.exerciseService.createExercise(exercise, true);
|
|
successCount++;
|
|
}
|
|
// Add more event type processing here as needed
|
|
|
|
} catch (error) {
|
|
console.error(`Error processing Nostr event:`, error);
|
|
// Continue with next event
|
|
}
|
|
}
|
|
|
|
console.log(`Successfully seeded ${successCount} items from Nostr`);
|
|
|
|
} catch (error) {
|
|
console.error('Error seeding from Nostr:', error);
|
|
}
|
|
}
|
|
|
|
async clearDatabase() {
|
|
if (!__DEV__) return;
|
|
|
|
try {
|
|
console.log('Clearing development database...');
|
|
|
|
await this.db.withTransactionAsync(async () => {
|
|
const tables = [
|
|
// Original tables
|
|
'exercises',
|
|
'exercise_tags',
|
|
'nostr_events',
|
|
'event_tags',
|
|
'cache_metadata',
|
|
'ndk_cache',
|
|
|
|
// New tables
|
|
'workouts',
|
|
'workout_exercises',
|
|
'workout_sets',
|
|
'templates',
|
|
'template_exercises'
|
|
];
|
|
|
|
for (const table of tables) {
|
|
try {
|
|
await this.db.runAsync(`DELETE FROM ${table}`);
|
|
console.log(`Cleared table: ${table}`);
|
|
} catch (error) {
|
|
console.log(`Table ${table} might not exist yet, skipping`);
|
|
}
|
|
}
|
|
});
|
|
|
|
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();
|
|
}
|
|
} |