From ba19482a41a498739a9e93a50cc22ad2559338ef Mon Sep 17 00:00:00 2001 From: mARTin Date: Sun, 22 Mar 2026 22:48:06 +0100 Subject: [PATCH] fix: prune deleted Synology calendars from settings list When loading calendar connections, the API now fetches the live calendar list from Synology and removes entries that no longer exist on the server. v1.57.2 Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- src/app/api/calendar/connections/route.ts | 30 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 439ca6a..de693fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.57.1", + "version": "1.57.2", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/app/api/calendar/connections/route.ts b/src/app/api/calendar/connections/route.ts index 20d0ec9..97b22ca 100644 --- a/src/app/api/calendar/connections/route.ts +++ b/src/app/api/calendar/connections/route.ts @@ -3,6 +3,7 @@ import { getServerSession } from 'next-auth'; import { authOptions } from "@/lib/auth"; import { prisma } from '@/lib/prisma'; import { refreshConnectionCache, RefreshableConnection } from '@/lib/calendar-cache'; +import { getUserCalendars as getSynologyCalendars } from '@/lib/synology-calendar'; // Get user's calendar connections export async function GET(request: NextRequest) { @@ -30,18 +31,39 @@ export async function GET(request: NextRequest) { } // Return calendar connections (without sensitive tokens) - const connections = user.calendarConnections.map(conn => { + // Prune deleted calendars from providers that support live listing + const connections = await Promise.all(user.calendarConnections.map(async (conn) => { let calendars = conn.calendars as any[] | null; // For Apple connections, filter out VTODO/Reminders collections - // that may have been stored before the VEVENT-only filter was added. - // Reminder list URLs contain '/reminders/' in the path. if (conn.provider === 'apple' && Array.isArray(calendars)) { calendars = calendars.filter((cal: any) => !cal.id?.includes('/reminders/') ); } + // For Synology connections, prune calendars deleted on the server + if (conn.provider === 'synology' && Array.isArray(calendars) && calendars.length > 0) { + try { + const [username, password] = conn.accessToken.split(':'); + const serverUrl = conn.refreshToken; + if (username && password && serverUrl) { + const freshCalendars = await getSynologyCalendars(serverUrl, username, password); + const freshIds = new Set(freshCalendars.map(c => c.id)); + const pruned = calendars.filter((c: any) => freshIds.has(c.id)); + if (pruned.length < calendars.length) { + calendars = pruned; + await prisma.calendarConnection.update({ + where: { id: conn.id }, + data: { calendars: pruned }, + }); + } + } + } catch (err) { + console.error('[CONNECTIONS] Synology calendar pruning failed:', err); + } + } + return { id: conn.id, provider: conn.provider, @@ -49,7 +71,7 @@ export async function GET(request: NextRequest) { createdAt: conn.createdAt, expiresAt: conn.expiresAt, }; - }); + })); return NextResponse.json({ connections }); } catch (error) {