My-Weekly-ToDo-List/src/app/api/calendar/background-sync/route.ts
mARTin 8842123caf feat: improve calendar sync, event modal, and task list management
- Fix All Day checkbox positioning in CalendarEventModal (own row)
- Add provider name to calendar dropdown (Google/Apple/Outlook)
- Optimistic UI updates after event save/delete (no reload needed)
- Force-refresh calendar cache after event mutations
- Reduce background sync interval from 5min to 2min
- Support forceRefresh in background-sync API
- Use shared Prisma singleton in tasks sync route
- Add per-provider task list fetching and sync checkboxes
- Add allDay support to event creation and editing

v1.4.0
2026-02-24 11:01:15 +01:00

64 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/lib/auth";
import { prisma } from '@/lib/prisma';
import { isCacheStale, refreshConnectionCache, RefreshableConnection } from '@/lib/calendar-cache';
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json().catch(() => ({}));
const { timeMin, timeMax, forceRefresh } = body;
const user = await prisma.user.findUnique({
where: { email: session.user.email },
include: { calendarConnections: true },
});
if (!user || user.calendarConnections.length === 0) {
return NextResponse.json({ queued: 0 });
}
const now = new Date();
const tMin = timeMin ? new Date(timeMin) : new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const tMax = timeMax ? new Date(timeMax) : new Date(now.getTime() + 14 * 24 * 60 * 60 * 1000);
const staleChecks = await Promise.all(
user.calendarConnections.map(async conn => ({
conn,
stale: forceRefresh || await isCacheStale(conn.id, tMin),
}))
);
const toRefresh = staleChecks.filter(c => c.stale).map(c => c.conn);
if (toRefresh.length > 0) {
// Fire-and-forget
Promise.allSettled(
toRefresh.map(conn => {
const rc: RefreshableConnection = {
dbId: conn.id,
userId: user.id,
id: conn.id,
provider: conn.provider as 'google' | 'apple' | 'outlook',
accessToken: conn.accessToken,
refreshToken: conn.refreshToken ?? undefined,
expiresAt: conn.expiresAt ?? undefined,
calendars: conn.calendars as any,
};
return refreshConnectionCache(rc, tMin, tMax);
})
).catch(e => console.error('[BG SYNC]', e));
}
return NextResponse.json({ queued: toRefresh.length });
} catch (error) {
console.error('[BG SYNC] Error:', error);
return NextResponse.json({ queued: 0 });
}
}