feat: init cloud calendar support (#14247)

#### PR Dependency Tree


* **PR #14247** 👈
  * **PR #14248**

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Google Calendar integration (disabled by default): link/unlink
accounts, OAuth flow, webhooks, real-time push, background sync,
workspace calendars with customizable items and date-range event
viewing.
* **GraphQL / Client**
* New queries & mutations for accounts, subscriptions, events,
providers, and workspace calendar management.
* **Localization**
* Added localized error message for calendar provider request failures.
* **Tests**
* Backend tests covering sync, webhook renewal, and error/error-recovery
scenarios.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-01-12 23:17:43 +08:00
committed by GitHub
parent a5b60cf679
commit 0bd8160ed4
40 changed files with 4047 additions and 2 deletions

View File

@@ -192,6 +192,57 @@ type BlobUploadedPart {
partNumber: Int!
}
type CalendarAccountObjectType {
calendarsCount: Int!
createdAt: DateTime!
displayName: String
email: String
id: String!
lastError: String
provider: CalendarProviderType!
providerAccountId: String!
refreshIntervalMinutes: Int!
status: String!
updatedAt: DateTime!
}
type CalendarEventObjectType {
allDay: Boolean!
description: String
endAtUtc: DateTime!
externalEventId: String!
id: String!
location: String
originalTimezone: String
recurrenceId: String
startAtUtc: DateTime!
status: String
subscriptionId: String!
title: String
}
type CalendarProviderRequestErrorDataType {
message: String!
status: Int!
}
enum CalendarProviderType {
CalDAV
Google
}
type CalendarSubscriptionObjectType {
accountId: String!
color: String
displayName: String
enabled: Boolean!
externalCalendarId: String!
id: String!
lastSyncAt: DateTime
provider: CalendarProviderType!
timezone: String
}
enum ChatHistoryOrder {
asc
desc
@@ -746,7 +797,7 @@ type EditorType {
name: String!
}
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToAddWorkspaceFileEmbeddingDataType | CopilotFailedToGenerateEmbeddingDataType | CopilotFailedToMatchContextDataType | CopilotFailedToMatchGlobalContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderNotSupportedDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidAppConfigDataType | InvalidAppConfigInputDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidIndexerInputDataType | InvalidLicenseToActivateDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidOauthResponseDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | InvalidSearchProviderRequestDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NoCopilotProviderAvailableDataType | NoMoreSeatDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CalendarProviderRequestErrorDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToAddWorkspaceFileEmbeddingDataType | CopilotFailedToGenerateEmbeddingDataType | CopilotFailedToMatchContextDataType | CopilotFailedToMatchGlobalContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderNotSupportedDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidAppConfigDataType | InvalidAppConfigInputDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidIndexerInputDataType | InvalidLicenseToActivateDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidOauthResponseDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | InvalidSearchProviderRequestDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NoCopilotProviderAvailableDataType | NoMoreSeatDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
enum ErrorNames {
ACCESS_DENIED
@@ -758,6 +809,7 @@ enum ErrorNames {
BLOB_INVALID
BLOB_NOT_FOUND
BLOB_QUOTA_EXCEEDED
CALENDAR_PROVIDER_REQUEST_ERROR
CANNOT_DELETE_ACCOUNT_WITH_OWNED_TEAM_WORKSPACE
CANNOT_DELETE_ALL_ADMIN_ACCOUNT
CANNOT_DELETE_OWN_ACCOUNT
@@ -1220,6 +1272,11 @@ type LimitedUserType {
hasPassword: Boolean
}
input LinkCalendarAccountInput {
provider: CalendarProviderType!
redirectUri: String
}
input ListUserInput {
features: [FeatureType!]
first: Int = 20
@@ -1402,6 +1459,7 @@ type Mutation {
inviteBatch(emails: [String!]!, sendInviteMail: Boolean @deprecated(reason: "never used"), workspaceId: String!): [InviteResult!]! @deprecated(reason: "use [inviteMembers] instead")
inviteMembers(emails: [String!]!, workspaceId: String!): [InviteResult!]!
leaveWorkspace(sendLeaveMail: Boolean @deprecated(reason: "no used anymore"), workspaceId: String!, workspaceName: String @deprecated(reason: "no longer used")): Boolean!
linkCalendarAccount(input: LinkCalendarAccountInput!): String!
"""mention user in a doc"""
mentionUser(input: MentionInput!): ID!
@@ -1469,9 +1527,11 @@ type Mutation {
"""Trigger generate missing titles cron job"""
triggerGenerateTitleCron: Boolean!
unlinkCalendarAccount(accountId: String!): Boolean!
"""update app configuration"""
updateAppConfig(updates: [UpdateAppConfigInput!]!): JSONObject!
updateCalendarAccount(accountId: String!, refreshIntervalMinutes: Int!): CalendarAccountObjectType
"""Update a comment content"""
updateComment(input: CommentUpdateInput!): Boolean!
@@ -1500,6 +1560,7 @@ type Mutation {
"""Update workspace"""
updateWorkspace(input: UpdateWorkspaceInput!): WorkspaceType!
updateWorkspaceCalendars(input: UpdateWorkspaceCalendarsInput!): WorkspaceCalendarObjectType!
"""Update ignored docs"""
updateWorkspaceEmbeddingIgnoredDocs(add: [String!], remove: [String!], workspaceId: String!): Int!
@@ -1705,6 +1766,10 @@ type Query {
"""Apply updates to a doc using LLM and return the merged markdown."""
applyDocUpdates(docId: String!, op: String!, updates: String!, workspaceId: String!): String!
calendarAccountCalendars(accountId: String!): [CalendarSubscriptionObjectType!]!
calendarAccounts: [CalendarAccountObjectType!]!
calendarEvents(from: DateTime!, to: DateTime!, workspaceCalendarId: String!): [CalendarEventObjectType!]!
calendarProviders: [CalendarProviderType!]!
collectAllBlobSizes: WorkspaceBlobSizes! @deprecated(reason: "use `user.quotaUsage` instead")
"""Get current user"""
@@ -1751,6 +1816,7 @@ type Query {
"""Get workspace by id"""
workspace(id: String!): WorkspaceType!
workspaceCalendars(workspaceId: String!): [WorkspaceCalendarObjectType!]!
"""Get workspace role permissions"""
workspaceRolePermissions(id: String!): WorkspaceRolePermissions! @deprecated(reason: "use WorkspaceType[permissions] instead")
@@ -2207,6 +2273,11 @@ input UpdateUserSettingsInput {
receiveMentionEmail: Boolean
}
input UpdateWorkspaceCalendarsInput {
items: [WorkspaceCalendarItemInput!]!
workspaceId: String!
}
input UpdateWorkspaceInput {
"""Enable AI"""
enableAi: Boolean
@@ -2331,6 +2402,30 @@ type WorkspaceBlobSizes {
size: SafeInt!
}
input WorkspaceCalendarItemInput {
colorOverride: String
sortOrder: Int
subscriptionId: String!
}
type WorkspaceCalendarItemObjectType {
colorOverride: String
enabled: Boolean!
id: String!
sortOrder: Int
subscriptionId: String!
}
type WorkspaceCalendarObjectType {
colorOverride: String
createdByUserId: String!
displayNameOverride: String
enabled: Boolean!
id: String!
items: [WorkspaceCalendarItemObjectType!]!
workspaceId: String!
}
type WorkspaceDocMeta {
createdAt: DateTime!
createdBy: EditorType