mirror of
https://github.com/DocNR/POWR.git
synced 2025-04-19 10:51:19 +00:00
removed mock data! using powr pack to seed library
This commit is contained in:
parent
5b706b3894
commit
80bdb87fdc
@ -3,7 +3,6 @@ import { View, ActivityIndicator, ScrollView, Text } from 'react-native';
|
||||
import { SQLiteProvider, openDatabaseSync, SQLiteDatabase } from 'expo-sqlite';
|
||||
import { schema } from '@/lib/db/schema';
|
||||
import { ExerciseService } from '@/lib/db/services/ExerciseService';
|
||||
import { DevSeederService } from '@/lib/db/services/DevSeederService';
|
||||
import { PublicationQueueService } from '@/lib/db/services/PublicationQueueService';
|
||||
import { FavoritesService } from '@/lib/db/services/FavoritesService';
|
||||
import { WorkoutService } from '@/lib/db/services/WorkoutService';
|
||||
@ -17,7 +16,6 @@ interface DatabaseServicesContextValue {
|
||||
exerciseService: ExerciseService | null;
|
||||
workoutService: WorkoutService | null;
|
||||
templateService: TemplateService | null;
|
||||
devSeeder: DevSeederService | null;
|
||||
publicationQueue: PublicationQueueService | null;
|
||||
favoritesService: FavoritesService | null;
|
||||
powrPackService: POWRPackService | null;
|
||||
@ -28,7 +26,6 @@ const DatabaseServicesContext = React.createContext<DatabaseServicesContextValue
|
||||
exerciseService: null,
|
||||
workoutService: null,
|
||||
templateService: null,
|
||||
devSeeder: null,
|
||||
publicationQueue: null,
|
||||
favoritesService: null,
|
||||
powrPackService: null,
|
||||
@ -64,6 +61,7 @@ const DelayedInitializer: React.FC<{children: React.ReactNode}> = ({children}) =
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
const [isReady, setIsReady] = React.useState(false);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
@ -71,7 +69,6 @@ export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
exerciseService: null,
|
||||
workoutService: null,
|
||||
templateService: null,
|
||||
devSeeder: null,
|
||||
publicationQueue: null,
|
||||
favoritesService: null,
|
||||
powrPackService: null,
|
||||
@ -83,8 +80,7 @@ export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
|
||||
// Effect to set NDK on services when it becomes available
|
||||
React.useEffect(() => {
|
||||
if (ndk && services.devSeeder && services.publicationQueue) {
|
||||
services.devSeeder.setNDK(ndk);
|
||||
if (ndk && services.publicationQueue) {
|
||||
services.publicationQueue.setNDK(ndk);
|
||||
}
|
||||
}, [ndk, services]);
|
||||
@ -129,7 +125,6 @@ export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
const exerciseService = new ExerciseService(db);
|
||||
const workoutService = new WorkoutService(db);
|
||||
const templateService = new TemplateService(db, exerciseService);
|
||||
const devSeeder = new DevSeederService(db, exerciseService);
|
||||
const publicationQueue = new PublicationQueueService(db);
|
||||
const favoritesService = new FavoritesService(db);
|
||||
const powrPackService = new POWRPackService(db);
|
||||
@ -139,7 +134,6 @@ export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
|
||||
// Initialize NDK on services if available
|
||||
if (ndk) {
|
||||
devSeeder.setNDK(ndk);
|
||||
publicationQueue.setNDK(ndk);
|
||||
}
|
||||
|
||||
@ -148,21 +142,14 @@ export function DatabaseProvider({ children }: DatabaseProviderProps) {
|
||||
exerciseService,
|
||||
workoutService,
|
||||
templateService,
|
||||
devSeeder,
|
||||
publicationQueue,
|
||||
favoritesService,
|
||||
powrPackService,
|
||||
db,
|
||||
});
|
||||
// Seed development database
|
||||
|
||||
// Display database info in development mode
|
||||
if (__DEV__) {
|
||||
console.log('[DB] Seeding development database...');
|
||||
try {
|
||||
await devSeeder.seedDatabase();
|
||||
} catch (seedError) {
|
||||
console.error('[DB] Error seeding database:', seedError);
|
||||
// Continue even if seeding fails
|
||||
}
|
||||
await logDatabaseInfo();
|
||||
}
|
||||
|
||||
@ -231,14 +218,6 @@ export function useTemplateService() {
|
||||
return context.templateService;
|
||||
}
|
||||
|
||||
export function useDevSeeder() {
|
||||
const context = React.useContext(DatabaseServicesContext);
|
||||
if (!context.devSeeder) {
|
||||
throw new Error('Dev seeder not initialized');
|
||||
}
|
||||
return context.devSeeder;
|
||||
}
|
||||
|
||||
export function usePublicationQueue() {
|
||||
const context = React.useContext(DatabaseServicesContext);
|
||||
if (!context.publicationQueue) {
|
||||
@ -269,4 +248,4 @@ export function useDatabase() {
|
||||
throw new Error('Database not initialized');
|
||||
}
|
||||
return context.db;
|
||||
}
|
||||
}
|
@ -13,77 +13,42 @@ import { PackageOpen, ArrowRight } from 'lucide-react-native';
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk-mobile';
|
||||
import { usePOWRPackService } from '@/components/DatabaseProvider';
|
||||
import { Clipboard } from 'react-native';
|
||||
|
||||
// Hardcoded test pack naddr
|
||||
const TEST_PACK_NADDR = 'naddr1qq88qmmhwgkhgetnwskhqctrdvqs6amnwvaz7tmwdaejumr0dsq3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3q25f8lj0pcq7xk3v68w4h9ldenhh3v3x97gumm5yl8e0mgq0dnvssxpqqqp6ng325rsl';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
export default function POWRPackSection() {
|
||||
const { ndk } = useNDK();
|
||||
const powrPackService = usePOWRPackService();
|
||||
const [featuredPacks, setFeaturedPacks] = useState<NDKEvent[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
// Subscribe to POWR packs (kind 30004 with powrpack hashtag)
|
||||
const { events, isLoading: isSubscribeLoading } = useSubscribe(
|
||||
ndk ? [{ kinds: [30004], '#t': ['powrpack'], limit: 10 }] : false,
|
||||
const { events, isLoading } = useSubscribe(
|
||||
ndk ? [{ kinds: [30004], '#t': ['powrpack', 'fitness', 'workout'], limit: 10 }] : false,
|
||||
{ enabled: !!ndk }
|
||||
);
|
||||
|
||||
// Set up test data on component mount
|
||||
useEffect(() => {
|
||||
const setupTestData = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
// For testing, create a mock event that mimics what we'd get from the network
|
||||
const testPack = new NDKEvent(ndk || undefined);
|
||||
testPack.kind = 30004;
|
||||
testPack.pubkey = '55127fc9e1c03c6b459a3bab72fdb99def1644c5f239bdd09f3e5fb401ed9b21';
|
||||
testPack.content = 'This is a test POWR Pack containing 2 workout templates and 2 exercises. Created for testing POWR Pack import functionality.';
|
||||
testPack.id = 'c1838367545275c12a969b7f1b84c60edbaec548332bfb4af7e2d12926090211';
|
||||
testPack.created_at = 1741832829;
|
||||
|
||||
// Add all the tags
|
||||
testPack.tags = [
|
||||
['d', 'powr-test-pack'],
|
||||
['name', 'POWR Test Pack'],
|
||||
['about', 'A test collection of workout templates and exercises for POWR app'],
|
||||
['a', '33402:55127fc9e1c03c6b459a3bab72fdb99def1644c5f239bdd09f3e5fb401ed9b21:e8256e9f70b87ad9fc4cf5712fe8f61641fc1313c608c38525c81537b5b411a5'],
|
||||
['a', '33402:55127fc9e1c03c6b459a3bab72fdb99def1644c5f239bdd09f3e5fb401ed9b21:404faf8c2bc3cf2477b7753b0888af48fd1416c3ff77a019fef89a8199826bcd'],
|
||||
['a', '33401:55127fc9e1c03c6b459a3bab72fdb99def1644c5f239bdd09f3e5fb401ed9b21:d25892222f1bb4a457c840c5c829915c4e2a0d1ced55b40d69e4682d9a8e3fb2'],
|
||||
['a', '33401:55127fc9e1c03c6b459a3bab72fdb99def1644c5f239bdd09f3e5fb401ed9b21:9f93ee6c8c314e7938ebf00e3de86e6e255c3ed48ad9763843758669092bb92a']
|
||||
];
|
||||
|
||||
// Always include the test pack in our featured packs
|
||||
setFeaturedPacks([testPack]);
|
||||
} catch (error) {
|
||||
console.error('Error setting up test data:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
setupTestData();
|
||||
}, [ndk]);
|
||||
|
||||
// Update featured packs when events change
|
||||
useEffect(() => {
|
||||
if (events.length > 0) {
|
||||
// Combine the test pack with any events from the subscription
|
||||
setFeaturedPacks(prevPacks => {
|
||||
// Filter out duplicates by ID
|
||||
const uniqueEvents = events.filter(event =>
|
||||
!prevPacks.some(pack => pack.id === event.id)
|
||||
);
|
||||
return [...prevPacks, ...uniqueEvents];
|
||||
});
|
||||
setFeaturedPacks(events);
|
||||
}
|
||||
}, [events]);
|
||||
|
||||
// Handle pack click
|
||||
const handlePackClick = (packEvent: NDKEvent) => {
|
||||
try {
|
||||
// Get dTag for the pack
|
||||
const dTag = findTagValue(packEvent.tags, 'd');
|
||||
if (!dTag) {
|
||||
throw new Error('Pack is missing identifier (d tag)');
|
||||
}
|
||||
|
||||
// Create shareable naddr
|
||||
const naddr = TEST_PACK_NADDR; // Use hardcoded test pack naddr for now
|
||||
const naddr = nip19.naddrEncode({
|
||||
kind: 30004,
|
||||
pubkey: packEvent.pubkey,
|
||||
identifier: dTag,
|
||||
relays: ['wss://relay.damus.io', 'wss://nos.lol', 'wss://relay.nostr.band']
|
||||
});
|
||||
|
||||
// Copy to clipboard
|
||||
Clipboard.setString(naddr);
|
||||
@ -104,8 +69,8 @@ export default function POWRPackSection() {
|
||||
router.push('/(packs)/manage');
|
||||
};
|
||||
|
||||
// Even if there are no network packs, we'll always show our test pack
|
||||
const showSection = true;
|
||||
// Only show section if we have packs or are loading
|
||||
const showSection = featuredPacks.length > 0 || isLoading;
|
||||
|
||||
if (!showSection) {
|
||||
return null;
|
||||
@ -182,7 +147,7 @@ export default function POWRPackSection() {
|
||||
<PackageOpen size={32} color="#6b7280" />
|
||||
<Text style={styles.emptyText}>No packs found</Text>
|
||||
<Button
|
||||
onPress={() => router.push('/(packs)/manage')}
|
||||
onPress={() => router.push('/(packs)/import')}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
style={styles.emptyButton}
|
||||
|
@ -1,297 +0,0 @@
|
||||
// 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, exerciseService);
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,290 +0,0 @@
|
||||
// lib/mocks/exercises.ts
|
||||
import { NostrEvent } from '@/types/nostr';
|
||||
import {
|
||||
ExerciseDisplay,
|
||||
ExerciseType,
|
||||
ExerciseCategory,
|
||||
Equipment,
|
||||
BaseExercise
|
||||
} from '@/types/exercise';
|
||||
import { generateId } from '@/utils/ids';
|
||||
|
||||
// Mock exercise definitions that will become our initial POWR library
|
||||
export const mockExerciseEvents: NostrEvent[] = [
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Stand with feet hip-width apart, barbell racked on shoulders. Bend knees and hips to squat down, keeping chest up. Drive through heels to stand.",
|
||||
tags: [
|
||||
["d", "bb-back-squat"],
|
||||
["title", "Barbell Back Squat"],
|
||||
["format", "weight", "reps", "rpe", "set_type"],
|
||||
["format_units", "kg", "count", "0-10", "warmup|normal|drop|failure"],
|
||||
["equipment", "barbell"],
|
||||
["difficulty", "intermediate"],
|
||||
["category", "legs"],
|
||||
["t", "compound"],
|
||||
["t", "squat"],
|
||||
["t", "legs"],
|
||||
["t", "quadriceps"]
|
||||
],
|
||||
created_at: 1708300800, // Feb 19, 2024
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr", // We'll update this when we create the POWR relay
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Stand with feet shoulder-width apart, barbell on floor. Hinge at hips, grip bar outside knees. Keep back flat, drive through heels to lift.",
|
||||
tags: [
|
||||
["d", "bb-deadlift"],
|
||||
["title", "Barbell Deadlift"],
|
||||
["format", "weight", "reps", "rpe", "set_type"],
|
||||
["format_units", "kg", "count", "0-10", "warmup|normal|drop|failure"],
|
||||
["equipment", "barbell"],
|
||||
["difficulty", "intermediate"],
|
||||
["category", "legs"],
|
||||
["t", "compound"],
|
||||
["t", "hinge"],
|
||||
["t", "legs"],
|
||||
["t", "posterior"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Lie on bench, feet flat on floor. Grip barbell slightly wider than shoulders. Lower bar to chest, press back up to start.",
|
||||
tags: [
|
||||
["d", "bb-bench-press"],
|
||||
["title", "Barbell Bench Press"],
|
||||
["format", "weight", "reps", "rpe", "set_type"],
|
||||
["format_units", "kg", "count", "0-10", "warmup|normal|drop|failure"],
|
||||
["equipment", "barbell"],
|
||||
["difficulty", "intermediate"],
|
||||
["category", "push"],
|
||||
["t", "compound"],
|
||||
["t", "push"],
|
||||
["t", "chest"],
|
||||
["t", "triceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Start in plank position. Lower body by bending elbows, keeping body straight. Push back up to start position.",
|
||||
tags: [
|
||||
["d", "pushup"],
|
||||
["title", "Push-Up"],
|
||||
["format", "reps", "set_type"],
|
||||
["format_units", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "bodyweight"],
|
||||
["difficulty", "beginner"],
|
||||
["category", "push"],
|
||||
["t", "bodyweight"],
|
||||
["t", "push"],
|
||||
["t", "chest"],
|
||||
["t", "triceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Hang from pull-up bar with overhand grip. Pull body up until chin clears bar, lower back to start.",
|
||||
tags: [
|
||||
["d", "pullup"],
|
||||
["title", "Pull-Up"],
|
||||
["format", "reps", "set_type"],
|
||||
["format_units", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "bodyweight"],
|
||||
["difficulty", "intermediate"],
|
||||
["category", "pull"],
|
||||
["t", "bodyweight"],
|
||||
["t", "pull"],
|
||||
["t", "back"],
|
||||
["t", "biceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Sit at machine, grip handles at shoulder height. Press handles up overhead, return to start position.",
|
||||
tags: [
|
||||
["d", "shoulder-press-machine"],
|
||||
["title", "Shoulder Press Machine"],
|
||||
["format", "weight", "reps", "set_type"],
|
||||
["format_units", "kg", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "machine"],
|
||||
["difficulty", "beginner"],
|
||||
["category", "push"],
|
||||
["t", "machine"],
|
||||
["t", "push"],
|
||||
["t", "shoulders"],
|
||||
["t", "triceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Stand with dumbbell in each hand at sides. Curl weights toward shoulders, keeping elbows close to body. Lower back down.",
|
||||
tags: [
|
||||
["d", "db-bicep-curl"],
|
||||
["title", "Dumbbell Bicep Curl"],
|
||||
["format", "weight", "reps", "set_type"],
|
||||
["format_units", "kg", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "dumbbell"],
|
||||
["difficulty", "beginner"],
|
||||
["category", "pull"],
|
||||
["t", "isolation"],
|
||||
["t", "pull"],
|
||||
["t", "biceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Attach rope to cable machine at top. Grip ends, pull down to chest level keeping elbows close. Control return.",
|
||||
tags: [
|
||||
["d", "cable-tricep-pushdown"],
|
||||
["title", "Cable Tricep Pushdown"],
|
||||
["format", "weight", "reps", "set_type"],
|
||||
["format_units", "kg", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "cable"],
|
||||
["difficulty", "beginner"],
|
||||
["category", "push"],
|
||||
["t", "isolation"],
|
||||
["t", "push"],
|
||||
["t", "triceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Kneel before cable machine, rope attachment at bottom. Pull rope toward forehead, keeping upper arms still. Lower with control.",
|
||||
tags: [
|
||||
["d", "cable-face-pull"],
|
||||
["title", "Cable Face Pull"],
|
||||
["format", "weight", "reps", "set_type"],
|
||||
["format_units", "kg", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "cable"],
|
||||
["difficulty", "intermediate"],
|
||||
["category", "pull"],
|
||||
["t", "isolation"],
|
||||
["t", "pull"],
|
||||
["t", "rear-deltoids"],
|
||||
["t", "upper-back"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
},
|
||||
{
|
||||
kind: 33401,
|
||||
content: "Stand with feet hip-width, holding kettlebell by horns at chest. Squat down keeping chest up, stand back up.",
|
||||
tags: [
|
||||
["d", "kb-goblet-squat"],
|
||||
["title", "Kettlebell Goblet Squat"],
|
||||
["format", "weight", "reps", "set_type"],
|
||||
["format_units", "kg", "count", "warmup|normal|drop|failure"],
|
||||
["equipment", "kettlebell"],
|
||||
["difficulty", "beginner"],
|
||||
["category", "legs"],
|
||||
["t", "compound"],
|
||||
["t", "squat"],
|
||||
["t", "legs"],
|
||||
["t", "quadriceps"]
|
||||
],
|
||||
created_at: 1708300800,
|
||||
id: generateId('nostr'),
|
||||
pubkey: "powr",
|
||||
sig: undefined
|
||||
}
|
||||
];
|
||||
|
||||
function getTagValue(tags: string[][], name: string): string | undefined {
|
||||
const tag = tags.find((tag: string[]) => tag[0] === name);
|
||||
return tag ? tag[1] : undefined;
|
||||
}
|
||||
|
||||
function getTags(tags: string[][]): string[] {
|
||||
return tags
|
||||
.filter((tag: string[]) => tag[0] === 't')
|
||||
.map((tag: string[]) => tag[1]);
|
||||
}
|
||||
|
||||
export function convertNostrToExercise(event: NostrEvent): ExerciseDisplay {
|
||||
const baseExercise: BaseExercise = {
|
||||
id: event.id || '',
|
||||
title: getTagValue(event.tags, 'title') || '',
|
||||
type: getTagValue(event.tags, 'equipment') === 'bodyweight'
|
||||
? 'bodyweight'
|
||||
: 'strength' as ExerciseType,
|
||||
category: getTagValue(event.tags, 'category') as ExerciseCategory,
|
||||
equipment: getTagValue(event.tags, 'equipment') as Equipment,
|
||||
description: event.content,
|
||||
format: getTagValue(event.tags, 'format')
|
||||
?.split(',')
|
||||
.reduce((acc: Record<string, boolean>, curr: string) => ({
|
||||
...acc,
|
||||
[curr]: true
|
||||
}), {}),
|
||||
format_units: getTagValue(event.tags, 'format_units')
|
||||
?.split(',')
|
||||
.reduce((acc: Record<string, string>, curr: string, i: number) => {
|
||||
const format = getTagValue(event.tags, 'format')?.split(',')[i];
|
||||
return format ? { ...acc, [format]: curr } : acc;
|
||||
}, {}),
|
||||
tags: getTags(event.tags),
|
||||
availability: {
|
||||
source: ['powr']
|
||||
},
|
||||
created_at: event.created_at * 1000
|
||||
};
|
||||
|
||||
// Convert to ExerciseDisplay
|
||||
return {
|
||||
...baseExercise,
|
||||
source: 'powr',
|
||||
isFavorite: false,
|
||||
usageCount: 0
|
||||
};
|
||||
}
|
||||
|
||||
// Export pre-converted exercises for easy testing
|
||||
export const mockExercises = mockExerciseEvents.map(convertNostrToExercise);
|
||||
|
||||
// Helper to seed the database
|
||||
export async function seedExercises(exerciseService: any) {
|
||||
try {
|
||||
const existingCount = (await exerciseService.getAllExercises()).length;
|
||||
if (existingCount === 0) {
|
||||
console.log('Seeding database with mock exercises...');
|
||||
for (const exercise of mockExercises) {
|
||||
await exerciseService.createExercise(exercise);
|
||||
}
|
||||
console.log('Successfully seeded database');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error seeding database:', error);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user