Initial commit for Start9 packaging
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,281 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
passwordHash String
|
||||
name String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
sessions Session[]
|
||||
exercises Exercise[]
|
||||
workouts Workout[]
|
||||
programs Program[]
|
||||
equipment Equipment[]
|
||||
contentItems ContentItem[]
|
||||
aiSuggestions AISuggestion[]
|
||||
userPreferences UserPreferences?
|
||||
|
||||
@@index([email])
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([token])
|
||||
}
|
||||
|
||||
model Exercise {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
name String
|
||||
description String?
|
||||
muscleGroups String // JSON array stored as text: ["chest", "triceps"]
|
||||
type String // barbell, dumbbell, machine, cable, bodyweight, cardio, kettlebell, other
|
||||
inputFields String @default("[\"sets\",\"reps\",\"weight\"]") // JSON array: sets, reps, weight, duration, distance, calories
|
||||
defaultWeightUnit String? // null = use user pref; "kg" for kettlebells, etc.
|
||||
isCustom Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
setLogs SetLog[]
|
||||
programExercises ProgramExercise[]
|
||||
|
||||
@@unique([userId, name])
|
||||
@@index([userId])
|
||||
@@index([type])
|
||||
}
|
||||
|
||||
model Workout {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
date DateTime
|
||||
name String?
|
||||
notes String?
|
||||
durationMinutes Int?
|
||||
difficulty Int? // 1-10 scale
|
||||
caloriesBurned Int?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
setLogs SetLog[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([date])
|
||||
}
|
||||
|
||||
model SetLog {
|
||||
id String @id @default(cuid())
|
||||
workoutId String
|
||||
exerciseId String
|
||||
setNumber Int
|
||||
reps Int?
|
||||
weight Float?
|
||||
weightUnit String @default("lbs")
|
||||
rpe Int? // Rate of Perceived Exertion (1-10)
|
||||
durationSeconds Int? // for timed exercises (assault bike, jump rope, planks)
|
||||
distance Float? // for distance-based exercises
|
||||
distanceUnit String? // "mi", "km", "m"
|
||||
calories Int? // for cardio machines that report calories
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
workout Workout @relation(fields: [workoutId], references: [id], onDelete: Cascade)
|
||||
exercise Exercise @relation(fields: [exerciseId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([workoutId])
|
||||
@@index([exerciseId])
|
||||
}
|
||||
|
||||
model Program {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
name String
|
||||
description String?
|
||||
type String // hypertrophy, strength, power, endurance, recovery
|
||||
durationWeeks Int
|
||||
startDate DateTime
|
||||
endDate DateTime?
|
||||
isActive Boolean @default(false)
|
||||
aiGenerated Boolean @default(false)
|
||||
aiNotes String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
weeks ProgramWeek[]
|
||||
aiSuggestions AISuggestion[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([isActive])
|
||||
}
|
||||
|
||||
model ProgramWeek {
|
||||
id String @id @default(cuid())
|
||||
programId String
|
||||
weekNumber Int
|
||||
phase String?
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
program Program @relation(fields: [programId], references: [id], onDelete: Cascade)
|
||||
days ProgramDay[]
|
||||
|
||||
@@unique([programId, weekNumber])
|
||||
@@index([programId])
|
||||
}
|
||||
|
||||
model ProgramDay {
|
||||
id String @id @default(cuid())
|
||||
weekId String
|
||||
dayOfWeek Int // 0-6 (Sunday-Saturday)
|
||||
name String?
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
week ProgramWeek @relation(fields: [weekId], references: [id], onDelete: Cascade)
|
||||
exercises ProgramExercise[]
|
||||
|
||||
@@unique([weekId, dayOfWeek])
|
||||
@@index([weekId])
|
||||
}
|
||||
|
||||
model ProgramExercise {
|
||||
id String @id @default(cuid())
|
||||
dayId String
|
||||
exerciseId String
|
||||
order Int
|
||||
sets Int?
|
||||
repsMin Int?
|
||||
repsMax Int?
|
||||
rpe Int?
|
||||
restSeconds Int?
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
day ProgramDay @relation(fields: [dayId], references: [id], onDelete: Cascade)
|
||||
exercise Exercise @relation(fields: [exerciseId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([dayId, order])
|
||||
@@index([dayId])
|
||||
@@index([exerciseId])
|
||||
}
|
||||
|
||||
model Equipment {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
name String
|
||||
type String // rack, barbell, dumbbell, plate, bench, etc.
|
||||
quantity Int
|
||||
weight Float? // for plates, dumbbells, etc.
|
||||
weightUnit String @default("lbs")
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, name])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model ContentItem {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
title String
|
||||
source String // pdf_upload, youtube, manual_entry
|
||||
sourceUrl String?
|
||||
content String?
|
||||
fullText String? // Full searchable text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
chunks ContentChunk[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([source])
|
||||
}
|
||||
|
||||
model ContentChunk {
|
||||
id String @id @default(cuid())
|
||||
contentItemId String
|
||||
chunkNumber Int
|
||||
text String
|
||||
pageNumber Int?
|
||||
timestamp Float? // For video timestamps
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
contentItem ContentItem @relation(fields: [contentItemId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([contentItemId])
|
||||
}
|
||||
|
||||
model AISuggestion {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
programId String?
|
||||
type String // exercise_recommendation, workout_adjustment, program_optimization, etc.
|
||||
suggestion String
|
||||
priority Int // 1-5 scale
|
||||
accepted Boolean?
|
||||
source String // rules, claude
|
||||
metadata String? // JSON metadata
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
program Program? @relation(fields: [programId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([userId])
|
||||
@@index([programId])
|
||||
@@index([type])
|
||||
}
|
||||
|
||||
model UserPreferences {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
theme String @default("system") // light, dark, system
|
||||
defaultWeightUnit String @default("lbs")
|
||||
defaultRestSeconds Int @default(90)
|
||||
enableClaudeAI Boolean @default(false)
|
||||
claudeApiKey String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import * as bcryptjs from "bcryptjs";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
interface ExerciseData {
|
||||
name: string;
|
||||
description: string;
|
||||
muscleGroups: string[];
|
||||
type: string;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Create default user
|
||||
const hashedPassword = await bcryptjs.hash("workout123", 10);
|
||||
|
||||
const user = await prisma.user.upsert({
|
||||
where: { email: "admin@local" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "admin@local",
|
||||
passwordHash: hashedPassword,
|
||||
name: "Admin User",
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created/verified user:", user.id);
|
||||
|
||||
// Create user preferences
|
||||
await prisma.userPreferences.upsert({
|
||||
where: { userId: user.id },
|
||||
update: {},
|
||||
create: {
|
||||
userId: user.id,
|
||||
theme: "system",
|
||||
defaultWeightUnit: "lbs",
|
||||
defaultRestSeconds: 90,
|
||||
enableClaudeAI: false,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Created/verified user preferences");
|
||||
|
||||
// Define exercises by muscle group
|
||||
const exercises: ExerciseData[] = [
|
||||
// Chest
|
||||
{
|
||||
name: "Bench Press",
|
||||
description: "Barbell bench press for chest development",
|
||||
muscleGroups: ["chest", "triceps", "shoulders"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Incline Bench Press",
|
||||
description: "Incline barbell bench press targeting upper chest",
|
||||
muscleGroups: ["chest", "shoulders", "triceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Dumbbell Fly",
|
||||
description: "Chest fly using dumbbells for stretch and squeeze",
|
||||
muscleGroups: ["chest"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Cable Crossover",
|
||||
description: "Cable machine chest fly for constant tension",
|
||||
muscleGroups: ["chest"],
|
||||
type: "cable",
|
||||
},
|
||||
{
|
||||
name: "Push-ups",
|
||||
description: "Bodyweight chest exercise",
|
||||
muscleGroups: ["chest", "triceps", "shoulders"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Dips (Chest)",
|
||||
description: "Weighted or bodyweight dips for chest and triceps",
|
||||
muscleGroups: ["chest", "triceps"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Incline Dumbbell Press",
|
||||
description: "Incline dumbbell bench press for upper chest",
|
||||
muscleGroups: ["chest", "shoulders", "triceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Decline Bench Press",
|
||||
description: "Decline barbell bench press for lower chest emphasis",
|
||||
muscleGroups: ["chest", "triceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
|
||||
// Back
|
||||
{
|
||||
name: "Deadlift",
|
||||
description: "Compound barbell deadlift for full posterior chain",
|
||||
muscleGroups: ["back", "legs", "glutes"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Barbell Row",
|
||||
description: "Barbell bent-over row for back strength",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Pull-ups",
|
||||
description: "Bodyweight pull-ups for back and biceps",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Lat Pulldown",
|
||||
description: "Machine lat pulldown for back width",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Cable Row",
|
||||
description: "Seated cable row for back strength",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "cable",
|
||||
},
|
||||
{
|
||||
name: "T-Bar Row",
|
||||
description: "T-bar row for mid-back thickness",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Dumbbell Row",
|
||||
description: "Single-arm dumbbell row for back development",
|
||||
muscleGroups: ["back", "biceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Face Pulls",
|
||||
description: "Cable face pulls for rear delts and upper back",
|
||||
muscleGroups: ["back", "shoulders"],
|
||||
type: "cable",
|
||||
},
|
||||
|
||||
// Shoulders
|
||||
{
|
||||
name: "Overhead Press",
|
||||
description: "Standing barbell overhead press for shoulder strength",
|
||||
muscleGroups: ["shoulders", "triceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Lateral Raise",
|
||||
description: "Dumbbell lateral raise for shoulder width",
|
||||
muscleGroups: ["shoulders"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Front Raise",
|
||||
description: "Front raise for anterior shoulder development",
|
||||
muscleGroups: ["shoulders"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Reverse Fly",
|
||||
description: "Rear delt fly for posterior shoulder",
|
||||
muscleGroups: ["shoulders", "back"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Arnold Press",
|
||||
description: "Arnold press for full shoulder development",
|
||||
muscleGroups: ["shoulders", "triceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Upright Row",
|
||||
description: "Barbell upright row for shoulder and trap development",
|
||||
muscleGroups: ["shoulders", "traps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Shrugs",
|
||||
description: "Barbell shrugs for trap development",
|
||||
muscleGroups: ["traps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Cable Lateral Raise",
|
||||
description: "Cable lateral raise for shoulder isolation",
|
||||
muscleGroups: ["shoulders"],
|
||||
type: "cable",
|
||||
},
|
||||
|
||||
// Legs
|
||||
{
|
||||
name: "Squat",
|
||||
description: "Barbell back squat for overall leg development",
|
||||
muscleGroups: ["legs", "glutes", "quads"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Front Squat",
|
||||
description: "Front squat with emphasis on quadriceps",
|
||||
muscleGroups: ["quads", "glutes"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Leg Press",
|
||||
description: "Machine leg press for lower body strength",
|
||||
muscleGroups: ["legs", "glutes", "quads"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Romanian Deadlift",
|
||||
description: "RDL for hamstring and lower back development",
|
||||
muscleGroups: ["hamstrings", "glutes", "back"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Leg Curl",
|
||||
description: "Machine leg curl for hamstring isolation",
|
||||
muscleGroups: ["hamstrings"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Leg Extension",
|
||||
description: "Machine leg extension for quadriceps isolation",
|
||||
muscleGroups: ["quads"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Calf Raise",
|
||||
description: "Standing calf raise for calf development",
|
||||
muscleGroups: ["calves"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Bulgarian Split Squat",
|
||||
description: "Single-leg squat variation for leg strength",
|
||||
muscleGroups: ["legs", "glutes", "quads"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Lunges",
|
||||
description: "Dumbbell lunges for unilateral leg development",
|
||||
muscleGroups: ["legs", "glutes", "quads"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Hip Thrust",
|
||||
description: "Barbell hip thrust for glute development",
|
||||
muscleGroups: ["glutes"],
|
||||
type: "barbell",
|
||||
},
|
||||
|
||||
// Arms
|
||||
{
|
||||
name: "Barbell Curl",
|
||||
description: "Barbell curl for bicep strength",
|
||||
muscleGroups: ["biceps"],
|
||||
type: "barbell",
|
||||
},
|
||||
{
|
||||
name: "Dumbbell Curl",
|
||||
description: "Dumbbell bicep curl for arm development",
|
||||
muscleGroups: ["biceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Hammer Curl",
|
||||
description: "Hammer curl for bicep and forearm development",
|
||||
muscleGroups: ["biceps", "forearms"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Tricep Pushdown",
|
||||
description: "Cable tricep pushdown for tricep isolation",
|
||||
muscleGroups: ["triceps"],
|
||||
type: "cable",
|
||||
},
|
||||
{
|
||||
name: "Skull Crusher",
|
||||
description: "Lying tricep extension for tricep development",
|
||||
muscleGroups: ["triceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Overhead Tricep Extension",
|
||||
description: "Standing tricep extension for arm development",
|
||||
muscleGroups: ["triceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
{
|
||||
name: "Preacher Curl",
|
||||
description: "Preacher curl for bicep isolation",
|
||||
muscleGroups: ["biceps"],
|
||||
type: "machine",
|
||||
},
|
||||
{
|
||||
name: "Concentration Curl",
|
||||
description: "Seated concentration curl for bicep peak",
|
||||
muscleGroups: ["biceps"],
|
||||
type: "dumbbell",
|
||||
},
|
||||
|
||||
// Core
|
||||
{
|
||||
name: "Plank",
|
||||
description: "Bodyweight plank for core stability",
|
||||
muscleGroups: ["core", "abs"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Hanging Leg Raise",
|
||||
description: "Hanging leg raise for lower abs",
|
||||
muscleGroups: ["abs", "core"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Cable Crunch",
|
||||
description: "Cable crunch for abdominal development",
|
||||
muscleGroups: ["abs"],
|
||||
type: "cable",
|
||||
},
|
||||
{
|
||||
name: "Ab Wheel Rollout",
|
||||
description: "Ab wheel for core and abs",
|
||||
muscleGroups: ["core", "abs"],
|
||||
type: "other",
|
||||
},
|
||||
{
|
||||
name: "Russian Twist",
|
||||
description: "Russian twist for obliques and core",
|
||||
muscleGroups: ["obliques", "core"],
|
||||
type: "bodyweight",
|
||||
},
|
||||
{
|
||||
name: "Pallof Press",
|
||||
description: "Pallof press for anti-rotation core stability",
|
||||
muscleGroups: ["core", "obliques"],
|
||||
type: "cable",
|
||||
},
|
||||
|
||||
// Cardio
|
||||
{
|
||||
name: "Running",
|
||||
description: "Running for cardiovascular endurance",
|
||||
muscleGroups: ["cardio"],
|
||||
type: "cardio",
|
||||
},
|
||||
{
|
||||
name: "Rowing",
|
||||
description: "Rowing machine for full-body cardio",
|
||||
muscleGroups: ["cardio"],
|
||||
type: "cardio",
|
||||
},
|
||||
{
|
||||
name: "Jump Rope",
|
||||
description: "Jump rope for cardio and footwork",
|
||||
muscleGroups: ["cardio"],
|
||||
type: "cardio",
|
||||
},
|
||||
{
|
||||
name: "Cycling",
|
||||
description: "Cycling for lower body cardio",
|
||||
muscleGroups: ["cardio"],
|
||||
type: "cardio",
|
||||
},
|
||||
];
|
||||
|
||||
// Create or update exercises
|
||||
for (const exercise of exercises) {
|
||||
await prisma.exercise.upsert({
|
||||
where: {
|
||||
userId_name: {
|
||||
userId: user.id,
|
||||
name: exercise.name,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
userId: user.id,
|
||||
name: exercise.name,
|
||||
description: exercise.description,
|
||||
muscleGroups: JSON.stringify(exercise.muscleGroups),
|
||||
type: exercise.type,
|
||||
isCustom: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Created/verified ${exercises.length} exercises`);
|
||||
}
|
||||
|
||||
main()
|
||||
.then(async () => {
|
||||
await prisma.$disconnect();
|
||||
})
|
||||
.catch(async (e) => {
|
||||
console.error(e);
|
||||
await prisma.$disconnect();
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user