From a617da99e239f7e4adcd7cb8502427558bea949d Mon Sep 17 00:00:00 2001 From: chauhan_s Date: Thu, 26 Mar 2026 23:46:25 +0530 Subject: [PATCH] fix: iCloud CalDAV discovery fallback and resolve calendarsCount in GraphQL (#14728) fixes #14696 iCloud was returning 400 Bad Request for /.well-known/caldav, which caused AFFiNE to fail before reaching the actual CalDAV endpoints. This change makes discovery fall back to the base CalDAV URL for that case, which lets the iCloud account link flow continue successfully. This also adds a GraphQL field resolver for CalendarAccountObjectType.calendarsCount. The field is requested by the frontend, but some mutation return paths were returning a raw account object without that computed value, which caused GraphQL to fail on a non-null field. --- ### Why this was needed iCloud rejected the standard well-known discovery probe with 400, even though the rest of the CalDAV flow worked. calendarsCount is a computed field used by the frontend, so it should be resolved by GraphQL rather than manually attached in individual service methods. --- ### How to test Generate an Apple app-specific password: [Apple Support](https://support.apple.com/en-gb/102654) In AFFiNE, add an iCloud CalDAV account using: your Apple Account email the new app-specific password Confirm the account links successfully and calendars load without the previous GraphQL error. ## Summary by CodeRabbit * **New Features** * Calendar accounts now display the total number of calendars. * **Bug Fixes** * Enhanced calendar discovery process to handle additional HTTP error conditions. --- .../src/plugins/calendar/providers/caldav.ts | 2 +- .../server/src/plugins/calendar/resolver.ts | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/backend/server/src/plugins/calendar/providers/caldav.ts b/packages/backend/server/src/plugins/calendar/providers/caldav.ts index e42348d4da..8c7210ede8 100644 --- a/packages/backend/server/src/plugins/calendar/providers/caldav.ts +++ b/packages/backend/server/src/plugins/calendar/providers/caldav.ts @@ -1020,7 +1020,7 @@ export class CalDAVProvider extends CalendarProvider { if (response.ok) { return response.url; } - if ([404, 405].includes(response.status)) { + if ([400, 404, 405].includes(response.status)) { return serverUrl; } const text = await response.text(); diff --git a/packages/backend/server/src/plugins/calendar/resolver.ts b/packages/backend/server/src/plugins/calendar/resolver.ts index dbba85fac6..134c751fdf 100644 --- a/packages/backend/server/src/plugins/calendar/resolver.ts +++ b/packages/backend/server/src/plugins/calendar/resolver.ts @@ -1,6 +1,7 @@ import { Args, GraphQLISODateTime, + Int, Mutation, Parent, ResolveField, @@ -75,6 +76,22 @@ export class UserCalendarResolver { export class CalendarAccountResolver { constructor(private readonly calendar: CalendarService) {} + @ResolveField(() => Int) + async calendarsCount( + @CurrentUser() user: CurrentUser, + @Parent() account: CalendarAccountObjectType + ) { + if (typeof account.calendarsCount === 'number') { + return account.calendarsCount; + } + + const calendars = await this.calendar.listAccountCalendars( + user.id, + account.id + ); + return calendars.length; + } + @ResolveField(() => [CalendarSubscriptionObjectType]) async calendars( @CurrentUser() user: CurrentUser,