rebreak-monorepo/backend/server/api/me/last-seen.post.ts
chahinebrini 0ca0afb1e1 feat(presence): online-status backend (Phase 1)
Insta-style Online-Status mit Following-Filter + User-opt-out:
- Profile.lastSeenAt + Profile.presenceVisible (default true)
- GET /api/presence/last-seen?userIds=... batch, server-side filter
  durch Follow-Relation + presenceVisible
- GET /api/me/following → User-IDs für client-side Channel-Filter
  (Supabase Realtime Presence hat keine server-side Filter)
- POST /api/me/presence-visibility Toggle
- POST /api/me/last-seen Heartbeat (Phase-1-Fallback bis Edge-Function)
- /api/auth/me extended um presenceVisible für Settings-Initial-State

DB-Layer nutzt raw SQL bis Migration auf staging gelaufen ist
(Prisma-Client refresh erst nach CI generate).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 06:23:08 +02:00

22 lines
692 B
TypeScript

/**
* POST /api/me/last-seen
*
* Heartbeat endpoint — sets Profile.lastSeenAt = NOW() for the authenticated user.
* No request body required.
*
* Phase 1 fallback: frontend calls this on a ~60s interval while app is foregrounded.
* Phase 2 (TODO): replace with Supabase Edge-Function triggered on presence-leave
* events for sub-second accuracy without client-side polling.
*
* Response: { lastSeenAt: ISOString }
*/
import { requireUser } from "../../utils/auth";
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const now = await touchLastSeen(user.id);
return { success: true, data: { lastSeenAt: now.toISOString() } };
});