b2e271c3ea
CI / update (push) Successful in 4m10s
Dependencies upgraded: - svelte 5.38→5.55, @sveltejs/kit 2.37→2.56, adapter-node 5.3→5.5 - mongoose 8→9, sharp 0.33→0.34, typescript 5→6 - lucide-svelte → @lucide/svelte 1.7 (Svelte 5 native package) - vite 7→8 with rolldown (build time 33s→14s) - Removed terser (esbuild/oxc default minifier is 20-100x faster) Infrastructure: - Removed Redis/ioredis cache layer — MongoDB handles caching natively - Deleted src/lib/server/cache.ts and all cache.get/set/invalidate usage - Removed redis-cli from deploy workflow, Redis env vars from .env.example Mongoose 9 migration: - Replaced deprecated `new: true` with `returnDocument: 'after'` (16 files) - Fixed strict query filter types for ObjectId/paymentId fields - Fixed season param type (string→number) in recipe API - Removed unused @ts-expect-error in WorkoutSession model
110 lines
3.5 KiB
TypeScript
110 lines
3.5 KiB
TypeScript
import { json } from '@sveltejs/kit';
|
|
import type { RequestHandler } from './$types';
|
|
import { dbConnect } from '$utils/db';
|
|
import { ActiveWorkout } from '$models/ActiveWorkout';
|
|
import { broadcast } from '$lib/server/sseManager';
|
|
|
|
// GET /api/fitness/workout/active — fetch current active workout
|
|
export const GET: RequestHandler = async ({ locals }) => {
|
|
const session = await locals.auth();
|
|
if (!session?.user?.nickname) {
|
|
return json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
try {
|
|
await dbConnect();
|
|
const doc = await ActiveWorkout.findOne({ userId: session.user.nickname }).lean();
|
|
if (!doc) {
|
|
return json({ active: false });
|
|
}
|
|
return json({ active: true, workout: doc });
|
|
} catch (error) {
|
|
console.error('Error fetching active workout:', error);
|
|
return json({ error: 'Failed to fetch active workout' }, { status: 500 });
|
|
}
|
|
};
|
|
|
|
// PUT /api/fitness/workout/active — create or update active workout state
|
|
export const PUT: RequestHandler = async ({ request, locals }) => {
|
|
const session = await locals.auth();
|
|
if (!session?.user?.nickname) {
|
|
return json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
try {
|
|
await dbConnect();
|
|
const data = await request.json();
|
|
const { name, mode, activityType, templateId, exercises, paused, elapsed, savedAt, expectedVersion, restStartedAt, restTotal, restExerciseIdx, restSetIdx } = data;
|
|
|
|
if (!name) {
|
|
return json({ error: 'Name is required' }, { status: 400 });
|
|
}
|
|
|
|
const userId = session.user.nickname;
|
|
const existing = await ActiveWorkout.findOne({ userId });
|
|
|
|
if (existing && expectedVersion != null && existing.version !== expectedVersion) {
|
|
// Conflict — client is out of date
|
|
return json(
|
|
{ error: 'Version conflict', workout: existing },
|
|
{ status: 409 }
|
|
);
|
|
}
|
|
|
|
const newVersion = existing ? existing.version + 1 : 1;
|
|
|
|
const doc = await ActiveWorkout.findOneAndUpdate(
|
|
{ userId },
|
|
{
|
|
$set: {
|
|
name,
|
|
mode: mode ?? 'manual',
|
|
activityType: activityType ?? null,
|
|
templateId: templateId ?? null,
|
|
exercises: exercises ?? [],
|
|
paused: paused ?? false,
|
|
elapsed: elapsed ?? 0,
|
|
savedAt: savedAt ?? Date.now(),
|
|
restStartedAt: restStartedAt ?? null,
|
|
restTotal: restTotal ?? 0,
|
|
restExerciseIdx: restExerciseIdx ?? -1,
|
|
restSetIdx: restSetIdx ?? -1,
|
|
version: newVersion
|
|
},
|
|
$setOnInsert: { userId }
|
|
},
|
|
{ upsert: true, returnDocument: 'after', lean: true }
|
|
);
|
|
|
|
// Broadcast to all other connected devices
|
|
broadcast(userId, 'update', doc);
|
|
|
|
return json({ workout: doc });
|
|
} catch (error) {
|
|
console.error('Error updating active workout:', error);
|
|
return json({ error: 'Failed to update active workout' }, { status: 500 });
|
|
}
|
|
};
|
|
|
|
// DELETE /api/fitness/workout/active — clear active workout (finish/cancel)
|
|
export const DELETE: RequestHandler = async ({ locals }) => {
|
|
const session = await locals.auth();
|
|
if (!session?.user?.nickname) {
|
|
return json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
try {
|
|
await dbConnect();
|
|
const userId = session.user.nickname;
|
|
await ActiveWorkout.deleteOne({ userId });
|
|
|
|
// Notify all devices that workout is finished
|
|
broadcast(userId, 'finished', { active: false });
|
|
|
|
return json({ ok: true });
|
|
} catch (error) {
|
|
console.error('Error deleting active workout:', error);
|
|
return json({ error: 'Failed to delete active workout' }, { status: 500 });
|
|
}
|
|
};
|