Initial commit for Start9 packaging

This commit is contained in:
MacPro
2026-02-28 09:27:26 -06:00
commit 1b64c45c52
124 changed files with 15671 additions and 0 deletions
Binary file not shown.
+281
View File
@@ -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])
}
+405
View File
@@ -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);
});