From 7c24b2521a6e1124b08786a66b32c9715373ae0a Mon Sep 17 00:00:00 2001
From: DarkSky <25152247+darkskygit@users.noreply.github.com>
Date: Wed, 14 Jan 2026 00:01:07 +0800
Subject: [PATCH] feat: reduce backend (#14251)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
#### PR Dependency Tree
* **PR #14251** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
## Summary by CodeRabbit
* **New Features**
* Current user profile now exposes access tokens, revealed tokens, and
detailed calendar accounts/subscriptions.
* Workspace now exposes permissions, calendars, calendar events, and a
workspace-scoped blob upload part URL.
* New document-update mutation for applying doc updates.
* **API Changes**
* validateAppConfig is now a query (mutation deprecated).
* Several legacy top-level calendar/blob endpoints deprecated in favor
of user/workspace fields.
* **Refactor**
* Calendar, blob-upload and access-token surfaces reorganized to use
user/workspace-centric fields.
✏️ Tip: You can customize this high-level summary in your review
settings.
---
.../e2e/notification/resolver.spec.ts | 2 +-
.../server/src/core/access-token/index.ts | 4 +-
.../server/src/core/access-token/resolver.ts | 62 ++-
.../server/src/core/access-token/types.ts | 22 +
.../server/src/core/config/resolver.ts | 20 +-
.../src/core/workspaces/resolvers/blob.ts | 57 ++-
.../server/src/plugins/calendar/index.ts | 16 +-
.../server/src/plugins/calendar/resolver.ts | 112 +++--
.../server/src/plugins/copilot/resolver.ts | 30 ++
.../server/src/plugins/indexer/service.ts | 93 ++--
packages/backend/server/src/schema.gql | 32 +-
.../graphql/src/graphql/access-token/list.gql | 16 +-
.../src/graphql/admin/validate-config.gql | 4 +-
.../src/graphql/blob-upload-part-url.gql | 12 +-
.../calendar/calendar-account-calendars.gql | 13 -
.../graphql/calendar/calendar-accounts.gql | 37 +-
.../src/graphql/calendar/calendar-events.gql | 33 +-
.../graphql/calendar/calendar-providers.gql | 4 +-
.../graphql/calendar/workspace-calendars.gql | 22 +-
.../src/graphql/copilot-apply-doc-updates.gql | 4 +-
.../fragments/current-user-profile.gql | 36 ++
.../src/graphql/get-current-user-profile.gql | 7 +
.../src/graphql/get-workspace-info.gql | 22 +
packages/common/graphql/src/graphql/index.ts | 235 ++++++----
.../src/graphql/notification-count.gql | 6 +-
.../graphql/src/graphql/server-config.gql | 1 +
packages/common/graphql/src/schema.ts | 412 ++++++++++++------
.../nbstore/src/__tests__/cloud-blob.spec.ts | 10 +-
.../common/nbstore/src/impls/cloud/blob.ts | 8 +-
.../blocksuite/ai/provider/copilot-client.ts | 4 +-
.../account-setting/integrations-panel.tsx | 8 +-
.../calendar/subscription-setting.tsx | 7 +-
.../src/modules/cloud/stores/access-token.ts | 7 +-
.../cloud/stores/user-copilot-quota.ts | 4 +-
.../src/modules/cloud/stores/user-feature.ts | 4 +-
.../src/modules/cloud/stores/user-quota.ts | 4 +-
.../src/modules/cloud/stores/user-settings.ts | 8 +-
.../modules/integration/entities/calendar.ts | 51 ++-
.../src/modules/integration/store/calendar.ts | 38 +-
.../notification/stores/notification.ts | 2 +-
.../src/modules/permissions/stores/guard.ts | 12 +-
41 files changed, 978 insertions(+), 503 deletions(-)
create mode 100644 packages/backend/server/src/core/access-token/types.ts
delete mode 100644 packages/common/graphql/src/graphql/calendar/calendar-account-calendars.gql
create mode 100644 packages/common/graphql/src/graphql/fragments/current-user-profile.gql
create mode 100644 packages/common/graphql/src/graphql/get-current-user-profile.gql
diff --git a/packages/backend/server/src/__tests__/e2e/notification/resolver.spec.ts b/packages/backend/server/src/__tests__/e2e/notification/resolver.spec.ts
index 1dd0748f3..8e2c2a53d 100644
--- a/packages/backend/server/src/__tests__/e2e/notification/resolver.spec.ts
+++ b/packages/backend/server/src/__tests__/e2e/notification/resolver.spec.ts
@@ -273,7 +273,7 @@ e2e('should mark notification as read', async t => {
const count = await app.gql({
query: notificationCountQuery,
});
- t.is(count.currentUser!.notificationCount, 0);
+ t.is(count.currentUser!.notifications.totalCount, 0);
// read again should work
for (const notification of notifications) {
diff --git a/packages/backend/server/src/core/access-token/index.ts b/packages/backend/server/src/core/access-token/index.ts
index 6df3b3fbe..0fd0bcc3c 100644
--- a/packages/backend/server/src/core/access-token/index.ts
+++ b/packages/backend/server/src/core/access-token/index.ts
@@ -1,8 +1,8 @@
import { Module } from '@nestjs/common';
-import { AccessTokenResolver } from './resolver';
+import { AccessTokenResolver, UserAccessTokenResolver } from './resolver';
@Module({
- providers: [AccessTokenResolver],
+ providers: [AccessTokenResolver, UserAccessTokenResolver],
})
export class AccessTokenModule {}
diff --git a/packages/backend/server/src/core/access-token/resolver.ts b/packages/backend/server/src/core/access-token/resolver.ts
index b80a83d27..cfb734d1e 100644
--- a/packages/backend/server/src/core/access-token/resolver.ts
+++ b/packages/backend/server/src/core/access-token/resolver.ts
@@ -3,34 +3,17 @@ import {
Field,
InputType,
Mutation,
- ObjectType,
+ Parent,
Query,
+ ResolveField,
Resolver,
} from '@nestjs/graphql';
+import { ActionForbidden } from '../../base';
import { Models } from '../../models';
import { CurrentUser } from '../auth/session';
-
-@ObjectType()
-class AccessToken {
- @Field()
- id!: string;
-
- @Field()
- name!: string;
-
- @Field()
- createdAt!: Date;
-
- @Field(() => Date, { nullable: true })
- expiresAt!: Date | null;
-}
-
-@ObjectType()
-class RevealedAccessToken extends AccessToken {
- @Field()
- token!: string;
-}
+import { UserType } from '../user';
+import { AccessToken, RevealedAccessToken } from './types';
@InputType()
class GenerateAccessTokenInput {
@@ -45,12 +28,16 @@ class GenerateAccessTokenInput {
export class AccessTokenResolver {
constructor(private readonly models: Models) {}
- @Query(() => [AccessToken])
+ @Query(() => [AccessToken], {
+ deprecationReason: 'use currentUser.accessTokens',
+ })
async accessTokens(@CurrentUser() user: CurrentUser): Promise {
return await this.models.accessToken.list(user.id);
}
- @Query(() => [RevealedAccessToken])
+ @Query(() => [RevealedAccessToken], {
+ deprecationReason: 'use currentUser.revealedAccessTokens',
+ })
async revealedAccessTokens(
@CurrentUser() user: CurrentUser
): Promise {
@@ -78,3 +65,30 @@ export class AccessTokenResolver {
return true;
}
}
+
+@Resolver(() => UserType)
+export class UserAccessTokenResolver {
+ constructor(private readonly models: Models) {}
+
+ @ResolveField(() => [AccessToken])
+ async accessTokens(
+ @CurrentUser() currentUser: CurrentUser,
+ @Parent() user: UserType
+ ): Promise {
+ if (!currentUser || currentUser.id !== user.id) {
+ throw new ActionForbidden();
+ }
+ return await this.models.accessToken.list(user.id);
+ }
+
+ @ResolveField(() => [RevealedAccessToken])
+ async revealedAccessTokens(
+ @CurrentUser() currentUser: CurrentUser,
+ @Parent() user: UserType
+ ): Promise {
+ if (!currentUser || currentUser.id !== user.id) {
+ throw new ActionForbidden();
+ }
+ return await this.models.accessToken.list(user.id, true);
+ }
+}
diff --git a/packages/backend/server/src/core/access-token/types.ts b/packages/backend/server/src/core/access-token/types.ts
new file mode 100644
index 000000000..63979ed88
--- /dev/null
+++ b/packages/backend/server/src/core/access-token/types.ts
@@ -0,0 +1,22 @@
+import { Field, ObjectType } from '@nestjs/graphql';
+
+@ObjectType()
+export class AccessToken {
+ @Field()
+ id!: string;
+
+ @Field()
+ name!: string;
+
+ @Field()
+ createdAt!: Date;
+
+ @Field(() => Date, { nullable: true })
+ expiresAt!: Date | null;
+}
+
+@ObjectType()
+export class RevealedAccessToken extends AccessToken {
+ @Field()
+ token!: string;
+}
diff --git a/packages/backend/server/src/core/config/resolver.ts b/packages/backend/server/src/core/config/resolver.ts
index 003973b72..9f37dc3fe 100644
--- a/packages/backend/server/src/core/config/resolver.ts
+++ b/packages/backend/server/src/core/config/resolver.ts
@@ -230,13 +230,31 @@ export class AppConfigResolver {
return await this.service.updateConfig(me.id, updates);
}
- @Mutation(() => [AppConfigValidateResult], {
+ @Query(() => [AppConfigValidateResult], {
description: 'validate app configuration',
})
async validateAppConfig(
@Args('updates', { type: () => [UpdateAppConfigInput] })
updates: UpdateAppConfigInput[]
): Promise {
+ return this.validateConfigInternal(updates);
+ }
+
+ @Mutation(() => [AppConfigValidateResult], {
+ description: 'validate app configuration',
+ deprecationReason: 'use Query.validateAppConfig',
+ name: 'validateAppConfig',
+ })
+ async validateAppConfigMutation(
+ @Args('updates', { type: () => [UpdateAppConfigInput] })
+ updates: UpdateAppConfigInput[]
+ ): Promise {
+ return this.validateConfigInternal(updates);
+ }
+
+ private validateConfigInternal(
+ updates: UpdateAppConfigInput[]
+ ): AppConfigValidateResult[] {
const errors = this.service.validateConfig(updates);
return updates.map(update => {
diff --git a/packages/backend/server/src/core/workspaces/resolvers/blob.ts b/packages/backend/server/src/core/workspaces/resolvers/blob.ts
index a50bcbe0a..d9966e978 100644
--- a/packages/backend/server/src/core/workspaces/resolvers/blob.ts
+++ b/packages/backend/server/src/core/workspaces/resolvers/blob.ts
@@ -156,6 +156,19 @@ export class WorkspaceBlobResolver {
return this.storage.totalSize(workspace.id);
}
+ @ResolveField(() => BlobUploadPart, {
+ description: 'Get blob upload part url',
+ })
+ async blobUploadPartUrl(
+ @CurrentUser() user: CurrentUser,
+ @Parent() workspace: WorkspaceType,
+ @Args('key') key: string,
+ @Args('uploadId') uploadId: string,
+ @Args('partNumber', { type: () => Int }) partNumber: number
+ ): Promise {
+ return this.getUploadPart(user, workspace.id, key, uploadId, partNumber);
+ }
+
@Query(() => WorkspaceBlobSizes, {
deprecationReason: 'use `user.quotaUsage` instead',
})
@@ -399,13 +412,40 @@ export class WorkspaceBlobResolver {
return key;
}
- @Mutation(() => BlobUploadPart)
+ @Mutation(() => BlobUploadPart, {
+ deprecationReason: 'use WorkspaceType.blobUploadPartUrl',
+ })
async getBlobUploadPartUrl(
@CurrentUser() user: CurrentUser,
@Args('workspaceId') workspaceId: string,
@Args('key') key: string,
@Args('uploadId') uploadId: string,
@Args('partNumber', { type: () => Int }) partNumber: number
+ ): Promise {
+ return this.getUploadPart(user, workspaceId, key, uploadId, partNumber);
+ }
+
+ @Mutation(() => Boolean)
+ async abortBlobUpload(
+ @CurrentUser() user: CurrentUser,
+ @Args('workspaceId') workspaceId: string,
+ @Args('key') key: string,
+ @Args('uploadId') uploadId: string
+ ) {
+ await this.ac
+ .user(user.id)
+ .workspace(workspaceId)
+ .assert('Workspace.Blobs.Write');
+
+ return this.storage.abortMultipartUpload(workspaceId, key, uploadId);
+ }
+
+ private async getUploadPart(
+ user: CurrentUser,
+ workspaceId: string,
+ key: string,
+ uploadId: string,
+ partNumber: number
): Promise {
await this.ac
.user(user.id)
@@ -429,21 +469,6 @@ export class WorkspaceBlobResolver {
};
}
- @Mutation(() => Boolean)
- async abortBlobUpload(
- @CurrentUser() user: CurrentUser,
- @Args('workspaceId') workspaceId: string,
- @Args('key') key: string,
- @Args('uploadId') uploadId: string
- ) {
- await this.ac
- .user(user.id)
- .workspace(workspaceId)
- .assert('Workspace.Blobs.Write');
-
- return this.storage.abortMultipartUpload(workspaceId, key, uploadId);
- }
-
@Mutation(() => Boolean)
async deleteBlob(
@CurrentUser() user: CurrentUser,
diff --git a/packages/backend/server/src/plugins/calendar/index.ts b/packages/backend/server/src/plugins/calendar/index.ts
index 31c7c7d7c..25e82ad5a 100644
--- a/packages/backend/server/src/plugins/calendar/index.ts
+++ b/packages/backend/server/src/plugins/calendar/index.ts
@@ -9,7 +9,14 @@ import { CalendarController } from './controller';
import { CalendarCronJobs } from './cron';
import { CalendarOAuthService } from './oauth';
import { CalendarProviderFactory, CalendarProviders } from './providers';
-import { CalendarResolver } from './resolver';
+import {
+ CalendarAccountResolver,
+ CalendarMutationResolver,
+ CalendarServerConfigResolver,
+ UserCalendarResolver,
+ WorkspaceCalendarEventsResolver,
+ WorkspaceCalendarResolver,
+} from './resolver';
import { CalendarService } from './service';
@Module({
@@ -20,7 +27,12 @@ import { CalendarService } from './service';
CalendarService,
CalendarOAuthService,
CalendarCronJobs,
- CalendarResolver,
+ CalendarServerConfigResolver,
+ UserCalendarResolver,
+ CalendarAccountResolver,
+ WorkspaceCalendarResolver,
+ WorkspaceCalendarEventsResolver,
+ CalendarMutationResolver,
],
controllers: [CalendarController],
})
diff --git a/packages/backend/server/src/plugins/calendar/resolver.ts b/packages/backend/server/src/plugins/calendar/resolver.ts
index efebf3404..6cad77a0b 100644
--- a/packages/backend/server/src/plugins/calendar/resolver.ts
+++ b/packages/backend/server/src/plugins/calendar/resolver.ts
@@ -2,13 +2,17 @@ import {
Args,
GraphQLISODateTime,
Mutation,
- Query,
+ Parent,
+ ResolveField,
Resolver,
} from '@nestjs/graphql';
-import { AuthenticationRequired } from '../../base';
+import { ActionForbidden, AuthenticationRequired } from '../../base';
import { CurrentUser } from '../../core/auth';
+import { ServerConfigType } from '../../core/config/types';
import { AccessController } from '../../core/permission';
+import { UserType } from '../../core/user';
+import { WorkspaceType } from '../../core/workspaces';
import { Models } from '../../models';
import { CalendarOAuthService } from './oauth';
import { CalendarProviderFactory, CalendarProviderName } from './providers';
@@ -22,70 +26,100 @@ import {
WorkspaceCalendarObjectType,
} from './types';
-@Resolver(() => CalendarAccountObjectType)
-export class CalendarResolver {
- constructor(
- private readonly calendar: CalendarService,
- private readonly oauth: CalendarOAuthService,
- private readonly models: Models,
- private readonly access: AccessController,
- private readonly providerFactory: CalendarProviderFactory
- ) {}
+@Resolver(() => ServerConfigType)
+export class CalendarServerConfigResolver {
+ constructor(private readonly providerFactory: CalendarProviderFactory) {}
- @Query(() => [CalendarAccountObjectType])
- async calendarAccounts(@CurrentUser() user: CurrentUser) {
+ @ResolveField(() => [CalendarProviderName])
+ calendarProviders() {
+ return this.providerFactory.providers;
+ }
+}
+
+@Resolver(() => UserType)
+export class UserCalendarResolver {
+ constructor(private readonly calendar: CalendarService) {}
+
+ @ResolveField(() => [CalendarAccountObjectType])
+ async calendarAccounts(
+ @CurrentUser() currentUser: CurrentUser,
+ @Parent() user: UserType
+ ) {
+ if (!currentUser || currentUser.id !== user.id) {
+ throw new ActionForbidden();
+ }
return await this.calendar.listAccounts(user.id);
}
+}
- @Query(() => [CalendarSubscriptionObjectType])
- async calendarAccountCalendars(
+@Resolver(() => CalendarAccountObjectType)
+export class CalendarAccountResolver {
+ constructor(private readonly calendar: CalendarService) {}
+
+ @ResolveField(() => [CalendarSubscriptionObjectType])
+ async calendars(
@CurrentUser() user: CurrentUser,
- @Args('accountId') accountId: string
+ @Parent() account: CalendarAccountObjectType
) {
- return await this.calendar.listAccountCalendars(user.id, accountId);
+ return await this.calendar.listAccountCalendars(user.id, account.id);
}
+}
- @Query(() => [WorkspaceCalendarObjectType])
- async workspaceCalendars(
+@Resolver(() => WorkspaceType)
+export class WorkspaceCalendarResolver {
+ constructor(
+ private readonly calendar: CalendarService,
+ private readonly access: AccessController
+ ) {}
+
+ @ResolveField(() => [WorkspaceCalendarObjectType])
+ async calendars(
@CurrentUser() user: CurrentUser,
- @Args('workspaceId') workspaceId: string
+ @Parent() workspace: WorkspaceType
) {
await this.access
.user(user.id)
- .workspace(workspaceId)
- .assert('Workspace.CreateDoc');
- return await this.calendar.getWorkspaceCalendars(workspaceId);
+ .workspace(workspace.id)
+ .assert('Workspace.Settings.Read');
+ return await this.calendar.getWorkspaceCalendars(workspace.id);
}
+}
- @Query(() => [CalendarEventObjectType])
- async calendarEvents(
+@Resolver(() => WorkspaceCalendarObjectType)
+export class WorkspaceCalendarEventsResolver {
+ constructor(
+ private readonly calendar: CalendarService,
+ private readonly access: AccessController
+ ) {}
+
+ @ResolveField(() => [CalendarEventObjectType])
+ async events(
@CurrentUser() user: CurrentUser,
- @Args('workspaceCalendarId') workspaceCalendarId: string,
+ @Parent() calendar: WorkspaceCalendarObjectType,
@Args({ name: 'from', type: () => GraphQLISODateTime }) from: Date,
@Args({ name: 'to', type: () => GraphQLISODateTime }) to: Date
) {
- const workspaceCalendar =
- await this.models.workspaceCalendar.get(workspaceCalendarId);
- if (!workspaceCalendar) {
- return [];
- }
-
await this.access
.user(user.id)
- .workspace(workspaceCalendar.workspaceId)
- .assert('Workspace.CreateDoc');
+ .workspace(calendar.workspaceId)
+ .assert('Workspace.Settings.Read');
return await this.calendar.listWorkspaceEvents({
- workspaceCalendarId,
+ workspaceCalendarId: calendar.id,
from,
to,
});
}
+}
- @Query(() => [CalendarProviderName])
- async calendarProviders() {
- return this.providerFactory.providers;
- }
+@Resolver(() => CalendarAccountObjectType)
+export class CalendarMutationResolver {
+ constructor(
+ private readonly calendar: CalendarService,
+ private readonly oauth: CalendarOAuthService,
+ private readonly models: Models,
+ private readonly access: AccessController
+ ) {}
@Mutation(() => String)
async linkCalendarAccount(
diff --git a/packages/backend/server/src/plugins/copilot/resolver.ts b/packages/backend/server/src/plugins/copilot/resolver.ts
index a106c562c..580fe7509 100644
--- a/packages/backend/server/src/plugins/copilot/resolver.ts
+++ b/packages/backend/server/src/plugins/copilot/resolver.ts
@@ -825,6 +825,7 @@ export class CopilotResolver {
@Query(() => String, {
description:
'Apply updates to a doc using LLM and return the merged markdown.',
+ deprecationReason: 'use Mutation.applyDocUpdates',
})
async applyDocUpdates(
@CurrentUser() user: CurrentUser,
@@ -836,6 +837,35 @@ export class CopilotResolver {
op: string,
@Args({ name: 'updates', type: () => String })
updates: string
+ ): Promise {
+ return this.applyDocUpdatesInternal(user, workspaceId, docId, op, updates);
+ }
+
+ @Mutation(() => String, {
+ description:
+ 'Apply updates to a doc using LLM and return the merged markdown.',
+ name: 'applyDocUpdates',
+ })
+ async applyDocUpdatesMutation(
+ @CurrentUser() user: CurrentUser,
+ @Args({ name: 'workspaceId', type: () => String })
+ workspaceId: string,
+ @Args({ name: 'docId', type: () => String })
+ docId: string,
+ @Args({ name: 'op', type: () => String })
+ op: string,
+ @Args({ name: 'updates', type: () => String })
+ updates: string
+ ): Promise {
+ return this.applyDocUpdatesInternal(user, workspaceId, docId, op, updates);
+ }
+
+ private async applyDocUpdatesInternal(
+ user: CurrentUser,
+ workspaceId: string,
+ docId: string,
+ op: string,
+ updates: string
): Promise {
await this.assertPermission(user, { workspaceId, docId });
diff --git a/packages/backend/server/src/plugins/indexer/service.ts b/packages/backend/server/src/plugins/indexer/service.ts
index abc2b8388..66d1d0eb9 100644
--- a/packages/backend/server/src/plugins/indexer/service.ts
+++ b/packages/backend/server/src/plugins/indexer/service.ts
@@ -230,64 +230,57 @@ export class IndexerService {
docId,
docSnapshot.blob
);
- if (result) {
- await this.write(
- SearchTable.doc,
- [
- {
- workspaceId,
- docId,
- title: result.title,
- summary: result.summary,
- // NOTE(@fengmk): journal is not supported yet
- // journal: result.journal,
- createdByUserId: docSnapshot.createdBy ?? '',
- updatedByUserId: docSnapshot.updatedBy ?? '',
- createdAt: docSnapshot.createdAt,
- updatedAt: docSnapshot.updatedAt,
- },
- ],
- options
- );
- await this.deleteBlocksByDocId(workspaceId, docId, options);
- await this.write(
- SearchTable.block,
- result.blocks.map(block => ({
+ await this.write(
+ SearchTable.doc,
+ [
+ {
workspaceId,
docId,
- blockId: block.blockId,
- content: block.content ?? '',
- flavour: block.flavour,
- blob: block.blob,
- refDocId: block.refDocId,
- ref: block.ref,
- parentFlavour: block.parentFlavour,
- parentBlockId: block.parentBlockId,
- additional: block.additional
- ? JSON.stringify(block.additional)
- : undefined,
- markdownPreview: undefined,
+ title: result.title,
+ summary: result.summary,
+ // NOTE(@fengmk): journal is not supported yet
+ // journal: result.journal,
createdByUserId: docSnapshot.createdBy ?? '',
updatedByUserId: docSnapshot.updatedBy ?? '',
createdAt: docSnapshot.createdAt,
updatedAt: docSnapshot.updatedAt,
- })),
- options
- );
-
- await this.queue.add('copilot.embedding.updateDoc', {
+ },
+ ],
+ options
+ );
+ await this.deleteBlocksByDocId(workspaceId, docId, options);
+ await this.write(
+ SearchTable.block,
+ result.blocks.map(block => ({
workspaceId,
docId,
- });
- this.logger.verbose(
- `synced doc ${workspaceId}/${docId} with ${result.blocks.length} blocks`
- );
- } else {
- this.logger.warn(
- `failed to parse ${workspaceId}/${docId}, no result returned`,
- metadata
- );
- }
+ blockId: block.blockId,
+ content: block.content ?? '',
+ flavour: block.flavour,
+ blob: block.blob,
+ refDocId: block.refDocId,
+ ref: block.ref,
+ parentFlavour: block.parentFlavour,
+ parentBlockId: block.parentBlockId,
+ additional: block.additional
+ ? JSON.stringify(block.additional)
+ : undefined,
+ markdownPreview: undefined,
+ createdByUserId: docSnapshot.createdBy ?? '',
+ updatedByUserId: docSnapshot.updatedBy ?? '',
+ createdAt: docSnapshot.createdAt,
+ updatedAt: docSnapshot.updatedAt,
+ })),
+ options
+ );
+
+ await this.queue.add('copilot.embedding.updateDoc', {
+ workspaceId,
+ docId,
+ });
+ this.logger.verbose(
+ `synced doc ${workspaceId}/${docId} with ${result.blocks.length} blocks`
+ );
} catch (err) {
this.logger.warn(
`failed to parse ${workspaceId}/${docId}: ${err}`,
diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql
index fa0f222d6..fbeb0d09c 100644
--- a/packages/backend/server/src/schema.gql
+++ b/packages/backend/server/src/schema.gql
@@ -193,6 +193,7 @@ type BlobUploadedPart {
}
type CalendarAccountObjectType {
+ calendars: [CalendarSubscriptionObjectType!]!
calendarsCount: Int!
createdAt: DateTime!
displayName: String
@@ -1384,6 +1385,9 @@ type Mutation {
"""Update workspace flags and features for admin"""
adminUpdateWorkspace(input: AdminUpdateWorkspaceInput!): AdminWorkspace
+
+ """Apply updates to a doc using LLM and return the merged markdown."""
+ applyDocUpdates(docId: String!, op: String!, updates: String!, workspaceId: String!): String!
approveMember(userId: String!, workspaceId: String!): Boolean!
"""Ban an user"""
@@ -1449,7 +1453,7 @@ type Mutation {
forkCopilotSession(options: ForkChatSessionInput!): String!
generateLicenseKey(sessionId: String!): String!
generateUserAccessToken(input: GenerateAccessTokenInput!): RevealedAccessToken!
- getBlobUploadPartUrl(key: String!, partNumber: Int!, uploadId: String!, workspaceId: String!): BlobUploadPart!
+ getBlobUploadPartUrl(key: String!, partNumber: Int!, uploadId: String!, workspaceId: String!): BlobUploadPart! @deprecated(reason: "use WorkspaceType.blobUploadPartUrl")
grantDocUserRoles(input: GrantDocUserRolesInput!): Boolean!
grantMember(permission: Permission!, userId: String!, workspaceId: String!): Boolean!
@@ -1572,7 +1576,7 @@ type Mutation {
uploadCommentAttachment(attachment: Upload!, docId: String!, workspaceId: String!): String!
"""validate app configuration"""
- validateAppConfig(updates: [UpdateAppConfigInput!]!): [AppConfigValidateResult!]!
+ validateAppConfig(updates: [UpdateAppConfigInput!]!): [AppConfigValidateResult!]! @deprecated(reason: "use Query.validateAppConfig")
verifyEmail(token: String!): Boolean!
}
@@ -1750,7 +1754,7 @@ type PublicUserType {
}
type Query {
- accessTokens: [AccessToken!]!
+ accessTokens: [AccessToken!]! @deprecated(reason: "use currentUser.accessTokens")
"""Get workspace detail for admin"""
adminWorkspace(id: String!): AdminWorkspace
@@ -1765,11 +1769,7 @@ type Query {
appConfig: JSONObject!
"""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!]!
+ applyDocUpdates(docId: String!, op: String!, updates: String!, workspaceId: String!): String! @deprecated(reason: "use Mutation.applyDocUpdates")
collectAllBlobSizes: WorkspaceBlobSizes! @deprecated(reason: "use `user.quotaUsage` instead")
"""Get current user"""
@@ -1794,7 +1794,7 @@ type Query {
"""query workspace embedding status"""
queryWorkspaceEmbeddingStatus(workspaceId: String!): ContextWorkspaceEmbeddingStatus!
- revealedAccessTokens: [RevealedAccessToken!]!
+ revealedAccessTokens: [RevealedAccessToken!]! @deprecated(reason: "use currentUser.revealedAccessTokens")
"""server config"""
serverConfig: ServerConfigType!
@@ -1814,9 +1814,11 @@ type Query {
"""Get users count"""
usersCount(filter: ListUserInput): Int!
+ """validate app configuration"""
+ validateAppConfig(updates: [UpdateAppConfigInput!]!): [AppConfigValidateResult!]!
+
"""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")
@@ -2048,6 +2050,7 @@ type ServerConfigType {
"""server base url"""
baseUrl: String!
+ calendarProviders: [CalendarProviderType!]!
"""credentials requirement"""
credentialsRequirement: CredentialsRequirementType!
@@ -2345,8 +2348,11 @@ type UserSettingsType {
}
type UserType {
+ accessTokens: [AccessToken!]!
+
"""User avatar url"""
avatarUrl: String
+ calendarAccounts: [CalendarAccountObjectType!]!
copilot(workspaceId: String): Copilot!
"""User email verified"""
@@ -2382,6 +2388,7 @@ type UserType {
notifications(pagination: PaginationInput!): PaginatedNotificationObjectType!
quota: UserQuotaType!
quotaUsage: UserQuotaUsageType!
+ revealedAccessTokens: [RevealedAccessToken!]!
"""Get user settings"""
settings: UserSettingsType!
@@ -2421,6 +2428,7 @@ type WorkspaceCalendarObjectType {
createdByUserId: String!
displayNameOverride: String
enabled: Boolean!
+ events(from: DateTime!, to: DateTime!): [CalendarEventObjectType!]!
id: String!
items: [WorkspaceCalendarItemObjectType!]!
workspaceId: String!
@@ -2511,11 +2519,15 @@ type WorkspaceType {
"""Search a specific table with aggregate"""
aggregate(input: AggregateInput!): AggregateResultObjectType!
+ """Get blob upload part url"""
+ blobUploadPartUrl(key: String!, partNumber: Int!, uploadId: String!): BlobUploadPart!
+
"""List blobs of workspace"""
blobs: [ListedBlob!]!
"""Blobs size of workspace"""
blobsSize: Int!
+ calendars: [WorkspaceCalendarObjectType!]!
"""Get comment changes of a doc"""
commentChanges(docId: String!, pagination: PaginationInput!): PaginatedCommentChangeObjectType!
diff --git a/packages/common/graphql/src/graphql/access-token/list.gql b/packages/common/graphql/src/graphql/access-token/list.gql
index 13dd31027..45b2af5ab 100644
--- a/packages/common/graphql/src/graphql/access-token/list.gql
+++ b/packages/common/graphql/src/graphql/access-token/list.gql
@@ -1,9 +1,11 @@
query listUserAccessTokens {
- revealedAccessTokens {
- id
- name
- createdAt
- expiresAt
- token
+ currentUser {
+ revealedAccessTokens {
+ id
+ name
+ createdAt
+ expiresAt
+ token
+ }
}
-}
\ No newline at end of file
+}
diff --git a/packages/common/graphql/src/graphql/admin/validate-config.gql b/packages/common/graphql/src/graphql/admin/validate-config.gql
index 603a9cf31..0ca494ffd 100644
--- a/packages/common/graphql/src/graphql/admin/validate-config.gql
+++ b/packages/common/graphql/src/graphql/admin/validate-config.gql
@@ -1,4 +1,4 @@
-mutation validateConfig($updates: [UpdateAppConfigInput!]!) {
+query validateConfig($updates: [UpdateAppConfigInput!]!) {
validateAppConfig(updates: $updates) {
module
key
@@ -6,4 +6,4 @@ mutation validateConfig($updates: [UpdateAppConfigInput!]!) {
valid
error
}
-}
\ No newline at end of file
+}
diff --git a/packages/common/graphql/src/graphql/blob-upload-part-url.gql b/packages/common/graphql/src/graphql/blob-upload-part-url.gql
index b8b3f9131..837fb84fd 100644
--- a/packages/common/graphql/src/graphql/blob-upload-part-url.gql
+++ b/packages/common/graphql/src/graphql/blob-upload-part-url.gql
@@ -1,7 +1,9 @@
-mutation getBlobUploadPartUrl($workspaceId: String!, $key: String!, $uploadId: String!, $partNumber: Int!) {
- getBlobUploadPartUrl(workspaceId: $workspaceId, key: $key, uploadId: $uploadId, partNumber: $partNumber) {
- uploadUrl
- headers
- expiresAt
+query getBlobUploadPartUrl($workspaceId: String!, $key: String!, $uploadId: String!, $partNumber: Int!) {
+ workspace(id: $workspaceId) {
+ blobUploadPartUrl(key: $key, uploadId: $uploadId, partNumber: $partNumber) {
+ uploadUrl
+ headers
+ expiresAt
+ }
}
}
diff --git a/packages/common/graphql/src/graphql/calendar/calendar-account-calendars.gql b/packages/common/graphql/src/graphql/calendar/calendar-account-calendars.gql
deleted file mode 100644
index f4c544180..000000000
--- a/packages/common/graphql/src/graphql/calendar/calendar-account-calendars.gql
+++ /dev/null
@@ -1,13 +0,0 @@
-query calendarAccountCalendars($accountId: String!) {
- calendarAccountCalendars(accountId: $accountId) {
- id
- accountId
- provider
- externalCalendarId
- displayName
- timezone
- color
- enabled
- lastSyncAt
- }
-}
diff --git a/packages/common/graphql/src/graphql/calendar/calendar-accounts.gql b/packages/common/graphql/src/graphql/calendar/calendar-accounts.gql
index 60f42fccf..330fcd098 100644
--- a/packages/common/graphql/src/graphql/calendar/calendar-accounts.gql
+++ b/packages/common/graphql/src/graphql/calendar/calendar-accounts.gql
@@ -1,15 +1,28 @@
query calendarAccounts {
- calendarAccounts {
- id
- provider
- providerAccountId
- displayName
- email
- status
- lastError
- refreshIntervalMinutes
- calendarsCount
- createdAt
- updatedAt
+ currentUser {
+ calendarAccounts {
+ id
+ provider
+ providerAccountId
+ displayName
+ email
+ status
+ lastError
+ refreshIntervalMinutes
+ calendarsCount
+ createdAt
+ updatedAt
+ calendars {
+ id
+ accountId
+ provider
+ externalCalendarId
+ displayName
+ timezone
+ color
+ enabled
+ lastSyncAt
+ }
+ }
}
}
diff --git a/packages/common/graphql/src/graphql/calendar/calendar-events.gql b/packages/common/graphql/src/graphql/calendar/calendar-events.gql
index 9d031d2f7..aafcf1670 100644
--- a/packages/common/graphql/src/graphql/calendar/calendar-events.gql
+++ b/packages/common/graphql/src/graphql/calendar/calendar-events.gql
@@ -1,16 +1,21 @@
-query calendarEvents($workspaceCalendarId: String!, $from: DateTime!, $to: DateTime!) {
- calendarEvents(workspaceCalendarId: $workspaceCalendarId, from: $from, to: $to) {
- id
- subscriptionId
- externalEventId
- recurrenceId
- status
- title
- description
- location
- startAtUtc
- endAtUtc
- originalTimezone
- allDay
+query calendarEvents($workspaceId: String!, $from: DateTime!, $to: DateTime!) {
+ workspace(id: $workspaceId) {
+ calendars {
+ id
+ events(from: $from, to: $to) {
+ id
+ subscriptionId
+ externalEventId
+ recurrenceId
+ status
+ title
+ description
+ location
+ startAtUtc
+ endAtUtc
+ originalTimezone
+ allDay
+ }
+ }
}
}
diff --git a/packages/common/graphql/src/graphql/calendar/calendar-providers.gql b/packages/common/graphql/src/graphql/calendar/calendar-providers.gql
index ab6ec2eb6..f66017c63 100644
--- a/packages/common/graphql/src/graphql/calendar/calendar-providers.gql
+++ b/packages/common/graphql/src/graphql/calendar/calendar-providers.gql
@@ -1,3 +1,5 @@
query calendarProviders {
- calendarProviders
+ serverConfig {
+ calendarProviders
+ }
}
diff --git a/packages/common/graphql/src/graphql/calendar/workspace-calendars.gql b/packages/common/graphql/src/graphql/calendar/workspace-calendars.gql
index f90a109fc..e42418f39 100644
--- a/packages/common/graphql/src/graphql/calendar/workspace-calendars.gql
+++ b/packages/common/graphql/src/graphql/calendar/workspace-calendars.gql
@@ -1,17 +1,19 @@
query workspaceCalendars($workspaceId: String!) {
- workspaceCalendars(workspaceId: $workspaceId) {
- id
- workspaceId
- createdByUserId
- displayNameOverride
- colorOverride
- enabled
- items {
+ workspace(id: $workspaceId) {
+ calendars {
id
- subscriptionId
- sortOrder
+ workspaceId
+ createdByUserId
+ displayNameOverride
colorOverride
enabled
+ items {
+ id
+ subscriptionId
+ sortOrder
+ colorOverride
+ enabled
+ }
}
}
}
diff --git a/packages/common/graphql/src/graphql/copilot-apply-doc-updates.gql b/packages/common/graphql/src/graphql/copilot-apply-doc-updates.gql
index 94b1e9508..1d67e3ed7 100644
--- a/packages/common/graphql/src/graphql/copilot-apply-doc-updates.gql
+++ b/packages/common/graphql/src/graphql/copilot-apply-doc-updates.gql
@@ -1,3 +1,3 @@
-query applyDocUpdates($workspaceId: String!, $docId: String!, $op: String!, $updates: String!) {
+mutation applyDocUpdates($workspaceId: String!, $docId: String!, $op: String!, $updates: String!) {
applyDocUpdates(workspaceId: $workspaceId, docId: $docId, op: $op, updates: $updates)
-}
\ No newline at end of file
+}
diff --git a/packages/common/graphql/src/graphql/fragments/current-user-profile.gql b/packages/common/graphql/src/graphql/fragments/current-user-profile.gql
new file mode 100644
index 000000000..f2a4b148a
--- /dev/null
+++ b/packages/common/graphql/src/graphql/fragments/current-user-profile.gql
@@ -0,0 +1,36 @@
+fragment CurrentUserProfile on UserType {
+ id
+ name
+ email
+ avatarUrl
+ emailVerified
+ features
+ settings {
+ receiveInvitationEmail
+ receiveMentionEmail
+ receiveCommentEmail
+ }
+ quota {
+ name
+ blobLimit
+ storageQuota
+ historyPeriod
+ memberLimit
+ humanReadable {
+ name
+ blobLimit
+ storageQuota
+ historyPeriod
+ memberLimit
+ }
+ }
+ quotaUsage {
+ storageQuota
+ }
+ copilot {
+ quota {
+ limit
+ used
+ }
+ }
+}
diff --git a/packages/common/graphql/src/graphql/get-current-user-profile.gql b/packages/common/graphql/src/graphql/get-current-user-profile.gql
new file mode 100644
index 000000000..fd786998a
--- /dev/null
+++ b/packages/common/graphql/src/graphql/get-current-user-profile.gql
@@ -0,0 +1,7 @@
+#import './fragments/current-user-profile.gql'
+
+query getCurrentUserProfile {
+ currentUser {
+ ...CurrentUserProfile
+ }
+}
diff --git a/packages/common/graphql/src/graphql/get-workspace-info.gql b/packages/common/graphql/src/graphql/get-workspace-info.gql
index 29bfe9d26..abd19fd9d 100644
--- a/packages/common/graphql/src/graphql/get-workspace-info.gql
+++ b/packages/common/graphql/src/graphql/get-workspace-info.gql
@@ -1,5 +1,27 @@
query getWorkspaceInfo($workspaceId: String!) {
workspace(id: $workspaceId) {
+ permissions {
+ Workspace_Administrators_Manage
+ Workspace_Blobs_List
+ Workspace_Blobs_Read
+ Workspace_Blobs_Write
+ Workspace_Copilot
+ Workspace_CreateDoc
+ Workspace_Delete
+ Workspace_Organize_Read
+ Workspace_Payment_Manage
+ Workspace_Properties_Create
+ Workspace_Properties_Delete
+ Workspace_Properties_Read
+ Workspace_Properties_Update
+ Workspace_Read
+ Workspace_Settings_Read
+ Workspace_Settings_Update
+ Workspace_Sync
+ Workspace_TransferOwner
+ Workspace_Users_Manage
+ Workspace_Users_Read
+ }
role
team
}
diff --git a/packages/common/graphql/src/graphql/index.ts b/packages/common/graphql/src/graphql/index.ts
index 8b7c4b2e0..1ace1d24b 100644
--- a/packages/common/graphql/src/graphql/index.ts
+++ b/packages/common/graphql/src/graphql/index.ts
@@ -58,6 +58,42 @@ export const credentialsRequirementsFragment = `fragment CredentialsRequirements
...PasswordLimits
}
}`;
+export const currentUserProfileFragment = `fragment CurrentUserProfile on UserType {
+ id
+ name
+ email
+ avatarUrl
+ emailVerified
+ features
+ settings {
+ receiveInvitationEmail
+ receiveMentionEmail
+ receiveCommentEmail
+ }
+ quota {
+ name
+ blobLimit
+ storageQuota
+ historyPeriod
+ memberLimit
+ humanReadable {
+ name
+ blobLimit
+ storageQuota
+ historyPeriod
+ memberLimit
+ }
+ }
+ quotaUsage {
+ storageQuota
+ }
+ copilot {
+ quota {
+ limit
+ used
+ }
+ }
+}`;
export const passwordLimitsFragment = `fragment PasswordLimits on PasswordLimitsType {
minLength
maxLength
@@ -88,12 +124,14 @@ export const listUserAccessTokensQuery = {
id: 'listUserAccessTokensQuery' as const,
op: 'listUserAccessTokens',
query: `query listUserAccessTokens {
- revealedAccessTokens {
- id
- name
- createdAt
- expiresAt
- token
+ currentUser {
+ revealedAccessTokens {
+ id
+ name
+ createdAt
+ expiresAt
+ token
+ }
}
}`,
};
@@ -444,10 +482,10 @@ export const updateAppConfigMutation = {
}`,
};
-export const validateConfigMutation = {
- id: 'validateConfigMutation' as const,
+export const validateConfigQuery = {
+ id: 'validateConfigQuery' as const,
op: 'validateConfig',
- query: `mutation validateConfig($updates: [UpdateAppConfigInput!]!) {
+ query: `query validateConfig($updates: [UpdateAppConfigInput!]!) {
validateAppConfig(updates: $updates) {
module
key
@@ -540,37 +578,16 @@ export const createBlobUploadMutation = {
}`,
};
-export const getBlobUploadPartUrlMutation = {
- id: 'getBlobUploadPartUrlMutation' as const,
+export const getBlobUploadPartUrlQuery = {
+ id: 'getBlobUploadPartUrlQuery' as const,
op: 'getBlobUploadPartUrl',
- query: `mutation getBlobUploadPartUrl($workspaceId: String!, $key: String!, $uploadId: String!, $partNumber: Int!) {
- getBlobUploadPartUrl(
- workspaceId: $workspaceId
- key: $key
- uploadId: $uploadId
- partNumber: $partNumber
- ) {
- uploadUrl
- headers
- expiresAt
- }
-}`,
-};
-
-export const calendarAccountCalendarsQuery = {
- id: 'calendarAccountCalendarsQuery' as const,
- op: 'calendarAccountCalendars',
- query: `query calendarAccountCalendars($accountId: String!) {
- calendarAccountCalendars(accountId: $accountId) {
- id
- accountId
- provider
- externalCalendarId
- displayName
- timezone
- color
- enabled
- lastSyncAt
+ query: `query getBlobUploadPartUrl($workspaceId: String!, $key: String!, $uploadId: String!, $partNumber: Int!) {
+ workspace(id: $workspaceId) {
+ blobUploadPartUrl(key: $key, uploadId: $uploadId, partNumber: $partNumber) {
+ uploadUrl
+ headers
+ expiresAt
+ }
}
}`,
};
@@ -579,18 +596,31 @@ export const calendarAccountsQuery = {
id: 'calendarAccountsQuery' as const,
op: 'calendarAccounts',
query: `query calendarAccounts {
- calendarAccounts {
- id
- provider
- providerAccountId
- displayName
- email
- status
- lastError
- refreshIntervalMinutes
- calendarsCount
- createdAt
- updatedAt
+ currentUser {
+ calendarAccounts {
+ id
+ provider
+ providerAccountId
+ displayName
+ email
+ status
+ lastError
+ refreshIntervalMinutes
+ calendarsCount
+ createdAt
+ updatedAt
+ calendars {
+ id
+ accountId
+ provider
+ externalCalendarId
+ displayName
+ timezone
+ color
+ enabled
+ lastSyncAt
+ }
+ }
}
}`,
};
@@ -598,20 +628,25 @@ export const calendarAccountsQuery = {
export const calendarEventsQuery = {
id: 'calendarEventsQuery' as const,
op: 'calendarEvents',
- query: `query calendarEvents($workspaceCalendarId: String!, $from: DateTime!, $to: DateTime!) {
- calendarEvents(workspaceCalendarId: $workspaceCalendarId, from: $from, to: $to) {
- id
- subscriptionId
- externalEventId
- recurrenceId
- status
- title
- description
- location
- startAtUtc
- endAtUtc
- originalTimezone
- allDay
+ query: `query calendarEvents($workspaceId: String!, $from: DateTime!, $to: DateTime!) {
+ workspace(id: $workspaceId) {
+ calendars {
+ id
+ events(from: $from, to: $to) {
+ id
+ subscriptionId
+ externalEventId
+ recurrenceId
+ status
+ title
+ description
+ location
+ startAtUtc
+ endAtUtc
+ originalTimezone
+ allDay
+ }
+ }
}
}`,
};
@@ -620,7 +655,9 @@ export const calendarProvidersQuery = {
id: 'calendarProvidersQuery' as const,
op: 'calendarProviders',
query: `query calendarProviders {
- calendarProviders
+ serverConfig {
+ calendarProviders
+ }
}`,
};
@@ -689,19 +726,21 @@ export const workspaceCalendarsQuery = {
id: 'workspaceCalendarsQuery' as const,
op: 'workspaceCalendars',
query: `query workspaceCalendars($workspaceId: String!) {
- workspaceCalendars(workspaceId: $workspaceId) {
- id
- workspaceId
- createdByUserId
- displayNameOverride
- colorOverride
- enabled
- items {
+ workspace(id: $workspaceId) {
+ calendars {
id
- subscriptionId
- sortOrder
+ workspaceId
+ createdByUserId
+ displayNameOverride
colorOverride
enabled
+ items {
+ id
+ subscriptionId
+ sortOrder
+ colorOverride
+ enabled
+ }
}
}
}`,
@@ -915,10 +954,10 @@ export const uploadCommentAttachmentMutation = {
file: true,
};
-export const applyDocUpdatesQuery = {
- id: 'applyDocUpdatesQuery' as const,
+export const applyDocUpdatesMutation = {
+ id: 'applyDocUpdatesMutation' as const,
op: 'applyDocUpdates',
- query: `query applyDocUpdates($workspaceId: String!, $docId: String!, $op: String!, $updates: String!) {
+ query: `mutation applyDocUpdates($workspaceId: String!, $docId: String!, $op: String!, $updates: String!) {
applyDocUpdates(
workspaceId: $workspaceId
docId: $docId
@@ -1748,6 +1787,17 @@ export const getCurrentUserFeaturesQuery = {
}`,
};
+export const getCurrentUserProfileQuery = {
+ id: 'getCurrentUserProfileQuery' as const,
+ op: 'getCurrentUserProfile',
+ query: `query getCurrentUserProfile {
+ currentUser {
+ ...CurrentUserProfile
+ }
+}
+${currentUserProfileFragment}`,
+};
+
export const getCurrentUserQuery = {
id: 'getCurrentUserQuery' as const,
op: 'getCurrentUser',
@@ -1998,6 +2048,28 @@ export const getWorkspaceInfoQuery = {
op: 'getWorkspaceInfo',
query: `query getWorkspaceInfo($workspaceId: String!) {
workspace(id: $workspaceId) {
+ permissions {
+ Workspace_Administrators_Manage
+ Workspace_Blobs_List
+ Workspace_Blobs_Read
+ Workspace_Blobs_Write
+ Workspace_Copilot
+ Workspace_CreateDoc
+ Workspace_Delete
+ Workspace_Organize_Read
+ Workspace_Payment_Manage
+ Workspace_Properties_Create
+ Workspace_Properties_Delete
+ Workspace_Properties_Read
+ Workspace_Properties_Update
+ Workspace_Read
+ Workspace_Settings_Read
+ Workspace_Settings_Update
+ Workspace_Sync
+ Workspace_TransferOwner
+ Workspace_Users_Manage
+ Workspace_Users_Read
+ }
role
team
}
@@ -2336,7 +2408,9 @@ export const notificationCountQuery = {
op: 'notificationCount',
query: `query notificationCount {
currentUser {
- notificationCount
+ notifications(pagination: {first: 1}) {
+ totalCount
+ }
}
}`,
};
@@ -2523,6 +2597,7 @@ export const serverConfigQuery = {
features
type
initialized
+ calendarProviders
credentialsRequirement {
...CredentialsRequirements
}
diff --git a/packages/common/graphql/src/graphql/notification-count.gql b/packages/common/graphql/src/graphql/notification-count.gql
index 42813d01d..b5c123fa0 100644
--- a/packages/common/graphql/src/graphql/notification-count.gql
+++ b/packages/common/graphql/src/graphql/notification-count.gql
@@ -1,5 +1,7 @@
query notificationCount {
- currentUser {
- notificationCount
+ currentUser {
+ notifications(pagination: { first: 1 }) {
+ totalCount
}
+ }
}
diff --git a/packages/common/graphql/src/graphql/server-config.gql b/packages/common/graphql/src/graphql/server-config.gql
index ac8408567..15e2176c9 100644
--- a/packages/common/graphql/src/graphql/server-config.gql
+++ b/packages/common/graphql/src/graphql/server-config.gql
@@ -9,6 +9,7 @@ query serverConfig {
features
type
initialized
+ calendarProviders
credentialsRequirement {
...CredentialsRequirements
}
diff --git a/packages/common/graphql/src/schema.ts b/packages/common/graphql/src/schema.ts
index c0736fbad..3f68defd5 100644
--- a/packages/common/graphql/src/schema.ts
+++ b/packages/common/graphql/src/schema.ts
@@ -246,6 +246,7 @@ export interface BlobUploadedPart {
export interface CalendarAccountObjectType {
__typename?: 'CalendarAccountObjectType';
+ calendars: Array;
calendarsCount: Scalars['Int']['output'];
createdAt: Scalars['DateTime']['output'];
displayName: Maybe;
@@ -1570,6 +1571,8 @@ export interface Mutation {
addWorkspaceFeature: Scalars['Boolean']['output'];
/** Update workspace flags and features for admin */
adminUpdateWorkspace: Maybe;
+ /** Apply updates to a doc using LLM and return the merged markdown. */
+ applyDocUpdates: Scalars['String']['output'];
approveMember: Scalars['Boolean']['output'];
/** Ban an user */
banUser: UserType;
@@ -1619,6 +1622,7 @@ export interface Mutation {
forkCopilotSession: Scalars['String']['output'];
generateLicenseKey: Scalars['String']['output'];
generateUserAccessToken: RevealedAccessToken;
+ /** @deprecated use WorkspaceType.blobUploadPartUrl */
getBlobUploadPartUrl: BlobUploadPart;
grantDocUserRoles: Scalars['Boolean']['output'];
grantMember: Scalars['Boolean']['output'];
@@ -1716,7 +1720,10 @@ export interface Mutation {
uploadAvatar: UserType;
/** Upload a comment attachment and return the access url */
uploadCommentAttachment: Scalars['String']['output'];
- /** validate app configuration */
+ /**
+ * validate app configuration
+ * @deprecated use Query.validateAppConfig
+ */
validateAppConfig: Array;
verifyEmail: Scalars['Boolean']['output'];
}
@@ -1769,6 +1776,13 @@ export interface MutationAdminUpdateWorkspaceArgs {
input: AdminUpdateWorkspaceInput;
}
+export interface MutationApplyDocUpdatesArgs {
+ docId: Scalars['String']['input'];
+ op: Scalars['String']['input'];
+ updates: Scalars['String']['input'];
+ workspaceId: Scalars['String']['input'];
+}
+
export interface MutationApproveMemberArgs {
userId: Scalars['String']['input'];
workspaceId: Scalars['String']['input'];
@@ -2387,6 +2401,7 @@ export interface PublicUserType {
export interface Query {
__typename?: 'Query';
+ /** @deprecated use currentUser.accessTokens */
accessTokens: Array;
/** Get workspace detail for admin */
adminWorkspace: Maybe;
@@ -2396,12 +2411,11 @@ export interface Query {
adminWorkspacesCount: Scalars['Int']['output'];
/** get the whole app configuration */
appConfig: Scalars['JSONObject']['output'];
- /** Apply updates to a doc using LLM and return the merged markdown. */
+ /**
+ * Apply updates to a doc using LLM and return the merged markdown.
+ * @deprecated use Mutation.applyDocUpdates
+ */
applyDocUpdates: Scalars['String']['output'];
- calendarAccountCalendars: Array;
- calendarAccounts: Array;
- calendarEvents: Array;
- calendarProviders: Array;
/** @deprecated use `user.quotaUsage` instead */
collectAllBlobSizes: WorkspaceBlobSizes;
/** Get current user */
@@ -2426,6 +2440,7 @@ export interface Query {
publicUserById: Maybe;
/** query workspace embedding status */
queryWorkspaceEmbeddingStatus: ContextWorkspaceEmbeddingStatus;
+ /** @deprecated use currentUser.revealedAccessTokens */
revealedAccessTokens: Array;
/** server config */
serverConfig: ServerConfigType;
@@ -2439,9 +2454,10 @@ export interface Query {
users: Array;
/** Get users count */
usersCount: Scalars['Int']['output'];
+ /** validate app configuration */
+ validateAppConfig: Array;
/** Get workspace by id */
workspace: WorkspaceType;
- workspaceCalendars: Array;
/**
* Get workspace role permissions
* @deprecated use WorkspaceType[permissions] instead
@@ -2470,16 +2486,6 @@ export interface QueryApplyDocUpdatesArgs {
workspaceId: Scalars['String']['input'];
}
-export interface QueryCalendarAccountCalendarsArgs {
- accountId: Scalars['String']['input'];
-}
-
-export interface QueryCalendarEventsArgs {
- from: Scalars['DateTime']['input'];
- to: Scalars['DateTime']['input'];
- workspaceCalendarId: Scalars['String']['input'];
-}
-
export interface QueryErrorArgs {
name: ErrorNames;
}
@@ -2524,12 +2530,12 @@ export interface QueryUsersCountArgs {
filter?: InputMaybe;
}
-export interface QueryWorkspaceArgs {
- id: Scalars['String']['input'];
+export interface QueryValidateAppConfigArgs {
+ updates: Array;
}
-export interface QueryWorkspaceCalendarsArgs {
- workspaceId: Scalars['String']['input'];
+export interface QueryWorkspaceArgs {
+ id: Scalars['String']['input'];
}
export interface QueryWorkspaceRolePermissionsArgs {
@@ -2754,6 +2760,7 @@ export interface ServerConfigType {
availableWorkspaceFeatures: Array;
/** server base url */
baseUrl: Scalars['String']['output'];
+ calendarProviders: Array;
/** credentials requirement */
credentialsRequirement: CredentialsRequirementType;
/** enabled server features */
@@ -3055,8 +3062,10 @@ export interface UserSettingsType {
export interface UserType {
__typename?: 'UserType';
+ accessTokens: Array;
/** User avatar url */
avatarUrl: Maybe;
+ calendarAccounts: Array;
copilot: Copilot;
/**
* User email verified
@@ -3085,6 +3094,7 @@ export interface UserType {
notifications: PaginatedNotificationObjectType;
quota: UserQuotaType;
quotaUsage: UserQuotaUsageType;
+ revealedAccessTokens: Array;
/** Get user settings */
settings: UserSettingsType;
subscriptions: Array;
@@ -3142,11 +3152,17 @@ export interface WorkspaceCalendarObjectType {
createdByUserId: Scalars['String']['output'];
displayNameOverride: Maybe;
enabled: Scalars['Boolean']['output'];
+ events: Array;
id: Scalars['String']['output'];
items: Array;
workspaceId: Scalars['String']['output'];
}
+export interface WorkspaceCalendarObjectTypeEventsArgs {
+ from: Scalars['DateTime']['input'];
+ to: Scalars['DateTime']['input'];
+}
+
export interface WorkspaceDocMeta {
__typename?: 'WorkspaceDocMeta';
createdAt: Scalars['DateTime']['output'];
@@ -3239,10 +3255,13 @@ export interface WorkspaceType {
__typename?: 'WorkspaceType';
/** Search a specific table with aggregate */
aggregate: AggregateResultObjectType;
+ /** Get blob upload part url */
+ blobUploadPartUrl: BlobUploadPart;
/** List blobs of workspace */
blobs: Array;
/** Blobs size of workspace */
blobsSize: Scalars['Int']['output'];
+ calendars: Array;
/** Get comment changes of a doc */
commentChanges: PaginatedCommentChangeObjectType;
/** Get comments of a doc */
@@ -3314,6 +3333,12 @@ export interface WorkspaceTypeAggregateArgs {
input: AggregateInput;
}
+export interface WorkspaceTypeBlobUploadPartUrlArgs {
+ key: Scalars['String']['input'];
+ partNumber: Scalars['Int']['input'];
+ uploadId: Scalars['String']['input'];
+}
+
export interface WorkspaceTypeCommentChangesArgs {
docId: Scalars['String']['input'];
pagination: PaginationInput;
@@ -3411,14 +3436,17 @@ export type ListUserAccessTokensQueryVariables = Exact<{
export type ListUserAccessTokensQuery = {
__typename?: 'Query';
- revealedAccessTokens: Array<{
- __typename?: 'RevealedAccessToken';
- id: string;
- name: string;
- createdAt: string;
- expiresAt: string | null;
- token: string;
- }>;
+ currentUser: {
+ __typename?: 'UserType';
+ revealedAccessTokens: Array<{
+ __typename?: 'RevealedAccessToken';
+ id: string;
+ name: string;
+ createdAt: string;
+ expiresAt: string | null;
+ token: string;
+ }>;
+ } | null;
};
export type RevokeUserAccessTokenMutationVariables = Exact<{
@@ -3793,12 +3821,12 @@ export type UpdateAppConfigMutation = {
updateAppConfig: any;
};
-export type ValidateConfigMutationVariables = Exact<{
+export type ValidateConfigQueryVariables = Exact<{
updates: Array | UpdateAppConfigInput;
}>;
-export type ValidateConfigMutation = {
- __typename?: 'Mutation';
+export type ValidateConfigQuery = {
+ __typename?: 'Query';
validateAppConfig: Array<{
__typename?: 'AppConfigValidateResult';
module: string;
@@ -3904,93 +3932,101 @@ export type CreateBlobUploadMutation = {
};
};
-export type GetBlobUploadPartUrlMutationVariables = Exact<{
+export type GetBlobUploadPartUrlQueryVariables = Exact<{
workspaceId: Scalars['String']['input'];
key: Scalars['String']['input'];
uploadId: Scalars['String']['input'];
partNumber: Scalars['Int']['input'];
}>;
-export type GetBlobUploadPartUrlMutation = {
- __typename?: 'Mutation';
- getBlobUploadPartUrl: {
- __typename?: 'BlobUploadPart';
- uploadUrl: string;
- headers: any | null;
- expiresAt: string | null;
- };
-};
-
-export type CalendarAccountCalendarsQueryVariables = Exact<{
- accountId: Scalars['String']['input'];
-}>;
-
-export type CalendarAccountCalendarsQuery = {
+export type GetBlobUploadPartUrlQuery = {
__typename?: 'Query';
- calendarAccountCalendars: Array<{
- __typename?: 'CalendarSubscriptionObjectType';
- id: string;
- accountId: string;
- provider: CalendarProviderType;
- externalCalendarId: string;
- displayName: string | null;
- timezone: string | null;
- color: string | null;
- enabled: boolean;
- lastSyncAt: string | null;
- }>;
+ workspace: {
+ __typename?: 'WorkspaceType';
+ blobUploadPartUrl: {
+ __typename?: 'BlobUploadPart';
+ uploadUrl: string;
+ headers: any | null;
+ expiresAt: string | null;
+ };
+ };
};
export type CalendarAccountsQueryVariables = Exact<{ [key: string]: never }>;
export type CalendarAccountsQuery = {
__typename?: 'Query';
- calendarAccounts: Array<{
- __typename?: 'CalendarAccountObjectType';
- id: string;
- provider: CalendarProviderType;
- providerAccountId: string;
- displayName: string | null;
- email: string | null;
- status: string;
- lastError: string | null;
- refreshIntervalMinutes: number;
- calendarsCount: number;
- createdAt: string;
- updatedAt: string;
- }>;
+ currentUser: {
+ __typename?: 'UserType';
+ calendarAccounts: Array<{
+ __typename?: 'CalendarAccountObjectType';
+ id: string;
+ provider: CalendarProviderType;
+ providerAccountId: string;
+ displayName: string | null;
+ email: string | null;
+ status: string;
+ lastError: string | null;
+ refreshIntervalMinutes: number;
+ calendarsCount: number;
+ createdAt: string;
+ updatedAt: string;
+ calendars: Array<{
+ __typename?: 'CalendarSubscriptionObjectType';
+ id: string;
+ accountId: string;
+ provider: CalendarProviderType;
+ externalCalendarId: string;
+ displayName: string | null;
+ timezone: string | null;
+ color: string | null;
+ enabled: boolean;
+ lastSyncAt: string | null;
+ }>;
+ }>;
+ } | null;
};
export type CalendarEventsQueryVariables = Exact<{
- workspaceCalendarId: Scalars['String']['input'];
+ workspaceId: Scalars['String']['input'];
from: Scalars['DateTime']['input'];
to: Scalars['DateTime']['input'];
}>;
export type CalendarEventsQuery = {
__typename?: 'Query';
- calendarEvents: Array<{
- __typename?: 'CalendarEventObjectType';
- id: string;
- subscriptionId: string;
- externalEventId: string;
- recurrenceId: string | null;
- status: string | null;
- title: string | null;
- description: string | null;
- location: string | null;
- startAtUtc: string;
- endAtUtc: string;
- originalTimezone: string | null;
- allDay: boolean;
- }>;
+ workspace: {
+ __typename?: 'WorkspaceType';
+ calendars: Array<{
+ __typename?: 'WorkspaceCalendarObjectType';
+ id: string;
+ events: Array<{
+ __typename?: 'CalendarEventObjectType';
+ id: string;
+ subscriptionId: string;
+ externalEventId: string;
+ recurrenceId: string | null;
+ status: string | null;
+ title: string | null;
+ description: string | null;
+ location: string | null;
+ startAtUtc: string;
+ endAtUtc: string;
+ originalTimezone: string | null;
+ allDay: boolean;
+ }>;
+ }>;
+ };
};
export type CalendarProvidersQueryVariables = Exact<{ [key: string]: never }>;
export type CalendarProvidersQuery = {
__typename?: 'Query';
- calendarProviders: Array;
+ serverConfig: {
+ __typename?: 'ServerConfigType';
+ calendarProviders: Array;
+ };
};
export type LinkCalendarAccountMutationVariables = Exact<{
@@ -4065,23 +4101,26 @@ export type WorkspaceCalendarsQueryVariables = Exact<{
export type WorkspaceCalendarsQuery = {
__typename?: 'Query';
- workspaceCalendars: Array<{
- __typename?: 'WorkspaceCalendarObjectType';
- id: string;
- workspaceId: string;
- createdByUserId: string;
- displayNameOverride: string | null;
- colorOverride: string | null;
- enabled: boolean;
- items: Array<{
- __typename?: 'WorkspaceCalendarItemObjectType';
+ workspace: {
+ __typename?: 'WorkspaceType';
+ calendars: Array<{
+ __typename?: 'WorkspaceCalendarObjectType';
id: string;
- subscriptionId: string;
- sortOrder: number | null;
+ workspaceId: string;
+ createdByUserId: string;
+ displayNameOverride: string | null;
colorOverride: string | null;
enabled: boolean;
+ items: Array<{
+ __typename?: 'WorkspaceCalendarItemObjectType';
+ id: string;
+ subscriptionId: string;
+ sortOrder: number | null;
+ colorOverride: string | null;
+ enabled: boolean;
+ }>;
}>;
- }>;
+ };
};
export type CancelSubscriptionMutationVariables = Exact<{
@@ -4326,15 +4365,15 @@ export type UploadCommentAttachmentMutation = {
uploadCommentAttachment: string;
};
-export type ApplyDocUpdatesQueryVariables = Exact<{
+export type ApplyDocUpdatesMutationVariables = Exact<{
workspaceId: Scalars['String']['input'];
docId: Scalars['String']['input'];
op: Scalars['String']['input'];
updates: Scalars['String']['input'];
}>;
-export type ApplyDocUpdatesQuery = {
- __typename?: 'Query';
+export type ApplyDocUpdatesMutation = {
+ __typename?: 'Mutation';
applyDocUpdates: string;
};
@@ -5722,6 +5761,43 @@ export type CredentialsRequirementsFragment = {
};
};
+export type CurrentUserProfileFragment = {
+ __typename?: 'UserType';
+ id: string;
+ name: string;
+ email: string;
+ avatarUrl: string | null;
+ emailVerified: boolean;
+ features: Array;
+ settings: {
+ __typename?: 'UserSettingsType';
+ receiveInvitationEmail: boolean;
+ receiveMentionEmail: boolean;
+ receiveCommentEmail: boolean;
+ };
+ quota: {
+ __typename?: 'UserQuotaType';
+ name: string;
+ blobLimit: number;
+ storageQuota: number;
+ historyPeriod: number;
+ memberLimit: number;
+ humanReadable: {
+ __typename?: 'UserQuotaHumanReadableType';
+ name: string;
+ blobLimit: string;
+ storageQuota: string;
+ historyPeriod: string;
+ memberLimit: string;
+ };
+ };
+ quotaUsage: { __typename?: 'UserQuotaUsageType'; storageQuota: number };
+ copilot: {
+ __typename?: 'Copilot';
+ quota: { __typename?: 'CopilotQuota'; limit: number | null; used: number };
+ };
+};
+
export type PasswordLimitsFragment = {
__typename?: 'PasswordLimitsType';
minLength: number;
@@ -5754,6 +5830,54 @@ export type GetCurrentUserFeaturesQuery = {
} | null;
};
+export type GetCurrentUserProfileQueryVariables = Exact<{
+ [key: string]: never;
+}>;
+
+export type GetCurrentUserProfileQuery = {
+ __typename?: 'Query';
+ currentUser: {
+ __typename?: 'UserType';
+ id: string;
+ name: string;
+ email: string;
+ avatarUrl: string | null;
+ emailVerified: boolean;
+ features: Array;
+ settings: {
+ __typename?: 'UserSettingsType';
+ receiveInvitationEmail: boolean;
+ receiveMentionEmail: boolean;
+ receiveCommentEmail: boolean;
+ };
+ quota: {
+ __typename?: 'UserQuotaType';
+ name: string;
+ blobLimit: number;
+ storageQuota: number;
+ historyPeriod: number;
+ memberLimit: number;
+ humanReadable: {
+ __typename?: 'UserQuotaHumanReadableType';
+ name: string;
+ blobLimit: string;
+ storageQuota: string;
+ historyPeriod: string;
+ memberLimit: string;
+ };
+ };
+ quotaUsage: { __typename?: 'UserQuotaUsageType'; storageQuota: number };
+ copilot: {
+ __typename?: 'Copilot';
+ quota: {
+ __typename?: 'CopilotQuota';
+ limit: number | null;
+ used: number;
+ };
+ };
+ } | null;
+};
+
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never }>;
export type GetCurrentUserQuery = {
@@ -6042,7 +6166,34 @@ export type GetWorkspaceInfoQueryVariables = Exact<{
export type GetWorkspaceInfoQuery = {
__typename?: 'Query';
- workspace: { __typename?: 'WorkspaceType'; role: Permission; team: boolean };
+ workspace: {
+ __typename?: 'WorkspaceType';
+ role: Permission;
+ team: boolean;
+ permissions: {
+ __typename?: 'WorkspacePermissions';
+ Workspace_Administrators_Manage: boolean;
+ Workspace_Blobs_List: boolean;
+ Workspace_Blobs_Read: boolean;
+ Workspace_Blobs_Write: boolean;
+ Workspace_Copilot: boolean;
+ Workspace_CreateDoc: boolean;
+ Workspace_Delete: boolean;
+ Workspace_Organize_Read: boolean;
+ Workspace_Payment_Manage: boolean;
+ Workspace_Properties_Create: boolean;
+ Workspace_Properties_Delete: boolean;
+ Workspace_Properties_Read: boolean;
+ Workspace_Properties_Update: boolean;
+ Workspace_Read: boolean;
+ Workspace_Settings_Read: boolean;
+ Workspace_Settings_Update: boolean;
+ Workspace_Sync: boolean;
+ Workspace_TransferOwner: boolean;
+ Workspace_Users_Manage: boolean;
+ Workspace_Users_Read: boolean;
+ };
+ };
};
export type GetWorkspacePageByIdQueryVariables = Exact<{
@@ -6454,7 +6605,13 @@ export type NotificationCountQueryVariables = Exact<{ [key: string]: never }>;
export type NotificationCountQuery = {
__typename?: 'Query';
- currentUser: { __typename?: 'UserType'; notificationCount: number } | null;
+ currentUser: {
+ __typename?: 'UserType';
+ notifications: {
+ __typename?: 'PaginatedNotificationObjectType';
+ totalCount: number;
+ };
+ } | null;
};
export type PricesQueryVariables = Exact<{ [key: string]: never }>;
@@ -6656,6 +6813,7 @@ export type ServerConfigQuery = {
features: Array;
type: ServerDeploymentType;
initialized: boolean;
+ calendarProviders: Array;
credentialsRequirement: {
__typename?: 'CredentialsRequirementType';
password: {
@@ -7101,15 +7259,20 @@ export type Queries =
variables: ListUsersQueryVariables;
response: ListUsersQuery;
}
+ | {
+ name: 'validateConfigQuery';
+ variables: ValidateConfigQueryVariables;
+ response: ValidateConfigQuery;
+ }
| {
name: 'listBlobsQuery';
variables: ListBlobsQueryVariables;
response: ListBlobsQuery;
}
| {
- name: 'calendarAccountCalendarsQuery';
- variables: CalendarAccountCalendarsQueryVariables;
- response: CalendarAccountCalendarsQuery;
+ name: 'getBlobUploadPartUrlQuery';
+ variables: GetBlobUploadPartUrlQueryVariables;
+ response: GetBlobUploadPartUrlQuery;
}
| {
name: 'calendarAccountsQuery';
@@ -7141,11 +7304,6 @@ export type Queries =
variables: ListCommentsQueryVariables;
response: ListCommentsQuery;
}
- | {
- name: 'applyDocUpdatesQuery';
- variables: ApplyDocUpdatesQueryVariables;
- response: ApplyDocUpdatesQuery;
- }
| {
name: 'listContextObjectQuery';
variables: ListContextObjectQueryVariables;
@@ -7261,6 +7419,11 @@ export type Queries =
variables: GetCurrentUserFeaturesQueryVariables;
response: GetCurrentUserFeaturesQuery;
}
+ | {
+ name: 'getCurrentUserProfileQuery';
+ variables: GetCurrentUserProfileQueryVariables;
+ response: GetCurrentUserProfileQuery;
+ }
| {
name: 'getCurrentUserQuery';
variables: GetCurrentUserQueryVariables;
@@ -7533,11 +7696,6 @@ export type Mutations =
variables: UpdateAppConfigMutationVariables;
response: UpdateAppConfigMutation;
}
- | {
- name: 'validateConfigMutation';
- variables: ValidateConfigMutationVariables;
- response: ValidateConfigMutation;
- }
| {
name: 'deleteBlobMutation';
variables: DeleteBlobMutationVariables;
@@ -7568,11 +7726,6 @@ export type Mutations =
variables: CreateBlobUploadMutationVariables;
response: CreateBlobUploadMutation;
}
- | {
- name: 'getBlobUploadPartUrlMutation';
- variables: GetBlobUploadPartUrlMutationVariables;
- response: GetBlobUploadPartUrlMutation;
- }
| {
name: 'linkCalendarAccountMutation';
variables: LinkCalendarAccountMutationVariables;
@@ -7648,6 +7801,11 @@ export type Mutations =
variables: UploadCommentAttachmentMutationVariables;
response: UploadCommentAttachmentMutation;
}
+ | {
+ name: 'applyDocUpdatesMutation';
+ variables: ApplyDocUpdatesMutationVariables;
+ response: ApplyDocUpdatesMutation;
+ }
| {
name: 'addContextBlobMutation';
variables: AddContextBlobMutationVariables;
diff --git a/packages/common/nbstore/src/__tests__/cloud-blob.spec.ts b/packages/common/nbstore/src/__tests__/cloud-blob.spec.ts
index 7be3d06f2..250a041ba 100644
--- a/packages/common/nbstore/src/__tests__/cloud-blob.spec.ts
+++ b/packages/common/nbstore/src/__tests__/cloud-blob.spec.ts
@@ -3,7 +3,7 @@ import {
BlobUploadMethod,
completeBlobUploadMutation,
createBlobUploadMutation,
- getBlobUploadPartUrlMutation,
+ getBlobUploadPartUrlQuery,
setBlobMutation,
workspaceBlobQuotaQuery,
} from '@affine/graphql';
@@ -128,10 +128,12 @@ test('falls back to graphql and aborts when multipart upload fails', async () =>
},
};
}
- if (query === getBlobUploadPartUrlMutation) {
+ if (query === getBlobUploadPartUrlQuery) {
return {
- getBlobUploadPartUrl: {
- uploadUrl: 'https://upload.example.com/part',
+ workspace: {
+ blobUploadPartUrl: {
+ uploadUrl: 'https://upload.example.com/part',
+ },
},
};
}
diff --git a/packages/common/nbstore/src/impls/cloud/blob.ts b/packages/common/nbstore/src/impls/cloud/blob.ts
index bdf2a86a0..58d5170d9 100644
--- a/packages/common/nbstore/src/impls/cloud/blob.ts
+++ b/packages/common/nbstore/src/impls/cloud/blob.ts
@@ -5,7 +5,7 @@ import {
completeBlobUploadMutation,
createBlobUploadMutation,
deleteBlobMutation,
- getBlobUploadPartUrlMutation,
+ getBlobUploadPartUrlQuery,
listBlobsQuery,
releaseDeletedBlobsMutation,
setBlobMutation,
@@ -265,16 +265,16 @@ export class CloudBlobStorage extends BlobStorageBase {
const chunk = data.subarray(start, end);
const part = await this.connection.gql({
- query: getBlobUploadPartUrlMutation,
+ query: getBlobUploadPartUrlQuery,
variables: { workspaceId: this.options.id, key, uploadId, partNumber },
context: { signal },
});
const res = await this.fetchWithTimeout(
- part.getBlobUploadPartUrl.uploadUrl,
+ part.workspace.blobUploadPartUrl.uploadUrl,
{
method: 'PUT',
- headers: part.getBlobUploadPartUrl.headers ?? undefined,
+ headers: part.workspace.blobUploadPartUrl.headers ?? undefined,
body: chunk,
signal,
timeout: UPLOAD_REQUEST_TIMEOUT,
diff --git a/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts b/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
index 63ac1bd49..506a7378d 100644
--- a/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
+++ b/packages/frontend/core/src/blocksuite/ai/provider/copilot-client.ts
@@ -6,7 +6,7 @@ import {
addContextCategoryMutation,
addContextDocMutation,
addContextFileMutation,
- applyDocUpdatesQuery,
+ applyDocUpdatesMutation,
cleanupCopilotSessionMutation,
createCopilotContextMutation,
createCopilotMessageMutation,
@@ -557,7 +557,7 @@ export class CopilotClient {
updates: string
) {
return this.gql({
- query: applyDocUpdatesQuery,
+ query: applyDocUpdatesMutation,
variables: {
workspaceId,
docId,
diff --git a/packages/frontend/core/src/desktop/dialogs/setting/account-setting/integrations-panel.tsx b/packages/frontend/core/src/desktop/dialogs/setting/account-setting/integrations-panel.tsx
index 3125901da..f4525659e 100644
--- a/packages/frontend/core/src/desktop/dialogs/setting/account-setting/integrations-panel.tsx
+++ b/packages/frontend/core/src/desktop/dialogs/setting/account-setting/integrations-panel.tsx
@@ -24,7 +24,9 @@ import {
import { CollapsibleWrapper } from '../layout';
import * as styles from './integrations-panel.css';
-type CalendarAccount = CalendarAccountsQuery['calendarAccounts'][number];
+type CalendarAccount = NonNullable<
+ CalendarAccountsQuery['currentUser']
+>['calendarAccounts'][number];
const providerMeta = {
[CalendarProviderType.Google]: {
@@ -66,8 +68,8 @@ export const IntegrationsPanel = () => {
context: { signal },
}),
]);
- setAccounts(accountsData.calendarAccounts);
- setProviders(providersData.calendarProviders);
+ setAccounts(accountsData.currentUser?.calendarAccounts ?? []);
+ setProviders(providersData.serverConfig.calendarProviders ?? []);
} catch (error) {
if (
signal?.aborted ||
diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/calendar/subscription-setting.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/calendar/subscription-setting.tsx
index 02ddcba9c..45528650d 100644
--- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/calendar/subscription-setting.tsx
+++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/calendar/subscription-setting.tsx
@@ -1,12 +1,13 @@
import { Checkbox } from '@affine/component';
-import type { CalendarAccountCalendarsQuery } from '@affine/graphql';
+import type { CalendarAccountsQuery } from '@affine/graphql';
import { cssVarV2 } from '@toeverything/theme/v2';
import { useCallback } from 'react';
import * as styles from './subscription-setting.css';
-type CalendarSubscription =
- CalendarAccountCalendarsQuery['calendarAccountCalendars'][number];
+type CalendarSubscription = NonNullable<
+ NonNullable['calendarAccounts'][number]
+>['calendars'][number];
export const SubscriptionSetting = ({
subscription,
diff --git a/packages/frontend/core/src/modules/cloud/stores/access-token.ts b/packages/frontend/core/src/modules/cloud/stores/access-token.ts
index d1d5d95f3..e96142dff 100644
--- a/packages/frontend/core/src/modules/cloud/stores/access-token.ts
+++ b/packages/frontend/core/src/modules/cloud/stores/access-token.ts
@@ -8,8 +8,9 @@ import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
-export type AccessToken =
- ListUserAccessTokensQuery['revealedAccessTokens'][number];
+export type AccessToken = NonNullable<
+ ListUserAccessTokensQuery['currentUser']
+>['revealedAccessTokens'][number];
export class AccessTokenStore extends Store {
constructor(private readonly gqlService: GraphQLService) {
@@ -22,7 +23,7 @@ export class AccessTokenStore extends Store {
context: { signal },
});
- return data.revealedAccessTokens;
+ return data.currentUser?.revealedAccessTokens ?? [];
}
async generateUserAccessToken(
diff --git a/packages/frontend/core/src/modules/cloud/stores/user-copilot-quota.ts b/packages/frontend/core/src/modules/cloud/stores/user-copilot-quota.ts
index ebe5b5737..187925671 100644
--- a/packages/frontend/core/src/modules/cloud/stores/user-copilot-quota.ts
+++ b/packages/frontend/core/src/modules/cloud/stores/user-copilot-quota.ts
@@ -1,4 +1,4 @@
-import { copilotQuotaQuery } from '@affine/graphql';
+import { getCurrentUserProfileQuery } from '@affine/graphql';
import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
@@ -10,7 +10,7 @@ export class UserCopilotQuotaStore extends Store {
async fetchUserCopilotQuota(abortSignal?: AbortSignal) {
const data = await this.graphqlService.gql({
- query: copilotQuotaQuery,
+ query: getCurrentUserProfileQuery,
context: {
signal: abortSignal,
},
diff --git a/packages/frontend/core/src/modules/cloud/stores/user-feature.ts b/packages/frontend/core/src/modules/cloud/stores/user-feature.ts
index 6176c30ce..e720bb27f 100644
--- a/packages/frontend/core/src/modules/cloud/stores/user-feature.ts
+++ b/packages/frontend/core/src/modules/cloud/stores/user-feature.ts
@@ -1,4 +1,4 @@
-import { getUserFeaturesQuery } from '@affine/graphql';
+import { getCurrentUserProfileQuery } from '@affine/graphql';
import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
@@ -10,7 +10,7 @@ export class UserFeatureStore extends Store {
async getUserFeatures(signal: AbortSignal) {
const data = await this.gqlService.gql({
- query: getUserFeaturesQuery,
+ query: getCurrentUserProfileQuery,
context: {
signal,
},
diff --git a/packages/frontend/core/src/modules/cloud/stores/user-quota.ts b/packages/frontend/core/src/modules/cloud/stores/user-quota.ts
index 70698060a..e738a458d 100644
--- a/packages/frontend/core/src/modules/cloud/stores/user-quota.ts
+++ b/packages/frontend/core/src/modules/cloud/stores/user-quota.ts
@@ -1,4 +1,4 @@
-import { quotaQuery } from '@affine/graphql';
+import { getCurrentUserProfileQuery } from '@affine/graphql';
import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
@@ -10,7 +10,7 @@ export class UserQuotaStore extends Store {
async fetchUserQuota(abortSignal?: AbortSignal) {
const data = await this.graphqlService.gql({
- query: quotaQuery,
+ query: getCurrentUserProfileQuery,
context: {
signal: abortSignal,
},
diff --git a/packages/frontend/core/src/modules/cloud/stores/user-settings.ts b/packages/frontend/core/src/modules/cloud/stores/user-settings.ts
index a8d8e94e0..5e93a222b 100644
--- a/packages/frontend/core/src/modules/cloud/stores/user-settings.ts
+++ b/packages/frontend/core/src/modules/cloud/stores/user-settings.ts
@@ -1,6 +1,6 @@
import {
- type GetUserSettingsQuery,
- getUserSettingsQuery,
+ type GetCurrentUserProfileQuery,
+ getCurrentUserProfileQuery,
type UpdateUserSettingsInput,
updateUserSettingsMutation,
} from '@affine/graphql';
@@ -9,7 +9,7 @@ import { Store } from '@toeverything/infra';
import type { GraphQLService } from '../services/graphql';
export type UserSettings = NonNullable<
- GetUserSettingsQuery['currentUser']
+ GetCurrentUserProfileQuery['currentUser']
>['settings'];
export type { UpdateUserSettingsInput };
@@ -21,7 +21,7 @@ export class UserSettingsStore extends Store {
async getUserSettings(): Promise {
const result = await this.gqlService.gql({
- query: getUserSettingsQuery,
+ query: getCurrentUserProfileQuery,
});
return result.currentUser?.settings;
}
diff --git a/packages/frontend/core/src/modules/integration/entities/calendar.ts b/packages/frontend/core/src/modules/integration/entities/calendar.ts
index 6d370bcd1..25be0e2e7 100644
--- a/packages/frontend/core/src/modules/integration/entities/calendar.ts
+++ b/packages/frontend/core/src/modules/integration/entities/calendar.ts
@@ -1,5 +1,4 @@
import type {
- CalendarAccountCalendarsQuery,
CalendarAccountsQuery,
CalendarEventsQuery,
WorkspaceCalendarItemInput,
@@ -16,20 +15,29 @@ export class CalendarIntegration extends Entity {
super();
}
- accounts$ = new LiveData(
- []
- );
+ accounts$ = new LiveData<
+ NonNullable<
+ CalendarAccountsQuery['currentUser']
+ >['calendarAccounts'][number][]
+ >([]);
accountCalendars$ = new LiveData<
Map<
string,
- CalendarAccountCalendarsQuery['calendarAccountCalendars'][number][]
+ NonNullable<
+ NonNullable<
+ CalendarAccountsQuery['currentUser']
+ >['calendarAccounts'][number]
+ >['calendars']
>
>(new Map());
workspaceCalendars$ = new LiveData<
- WorkspaceCalendarsQuery['workspaceCalendars'][number][]
+ WorkspaceCalendarsQuery['workspace']['calendars'][number][]
>([]);
readonly eventsByDateMap$ = new LiveData<
- Map
+ Map<
+ string,
+ CalendarEventsQuery['workspace']['calendars'][number]['events'][number][]
+ >
>(new Map());
readonly eventDates$ = LiveData.computed(get => {
const eventsByDateMap = get(this.eventsByDateMap$);
@@ -48,7 +56,11 @@ export class CalendarIntegration extends Entity {
const subscriptionInfo = new Map<
string,
{
- subscription: CalendarAccountCalendarsQuery['calendarAccountCalendars'][number];
+ subscription: NonNullable<
+ NonNullable<
+ CalendarAccountsQuery['currentUser']
+ >['calendarAccounts'][number]
+ >['calendars'][number];
colorOverride?: string | null;
}
>();
@@ -113,23 +125,16 @@ export class CalendarIntegration extends Entity {
const calendarsByAccount = new Map<
string,
- CalendarAccountCalendarsQuery['calendarAccountCalendars'][number][]
+ NonNullable<
+ NonNullable<
+ CalendarAccountsQuery['currentUser']
+ >['calendarAccounts'][number]
+ >['calendars']
>();
- await Promise.all(
- accounts.map(async account => {
- try {
- const calendars = await this.store.fetchAccountCalendars(
- account.id,
- signal
- );
- calendarsByAccount.set(account.id, calendars);
- } catch (error) {
- console.error('Failed to load calendar subscriptions', error);
- calendarsByAccount.set(account.id, []);
- }
- })
- );
+ accounts.forEach(account => {
+ calendarsByAccount.set(account.id, account.calendars ?? []);
+ });
this.accountCalendars$.setValue(calendarsByAccount);
return calendarsByAccount;
diff --git a/packages/frontend/core/src/modules/integration/store/calendar.ts b/packages/frontend/core/src/modules/integration/store/calendar.ts
index 6fc5d6bcd..e56405e0f 100644
--- a/packages/frontend/core/src/modules/integration/store/calendar.ts
+++ b/packages/frontend/core/src/modules/integration/store/calendar.ts
@@ -1,6 +1,4 @@
import {
- type CalendarAccountCalendarsQuery,
- calendarAccountCalendarsQuery,
type CalendarAccountsQuery,
calendarAccountsQuery,
type CalendarEventsQuery,
@@ -34,38 +32,27 @@ export class CalendarStore extends Store {
async fetchAccounts(signal?: AbortSignal) {
const gql = this.gql;
- if (!gql) return [] satisfies CalendarAccountsQuery['calendarAccounts'];
+ if (!gql)
+ return [] satisfies NonNullable<
+ CalendarAccountsQuery['currentUser']
+ >['calendarAccounts'];
const data = await gql({
query: calendarAccountsQuery,
context: { signal },
});
- return data.calendarAccounts;
- }
-
- async fetchAccountCalendars(accountId: string, signal?: AbortSignal) {
- const gql = this.gql;
- if (!gql) {
- return [] satisfies CalendarAccountCalendarsQuery['calendarAccountCalendars'];
- }
- const data = await gql({
- query: calendarAccountCalendarsQuery,
- variables: { accountId },
- context: { signal },
- });
- return data.calendarAccountCalendars;
+ return data.currentUser?.calendarAccounts ?? [];
}
async fetchWorkspaceCalendars(signal?: AbortSignal) {
const gql = this.gql;
- if (!gql) {
- return [] satisfies WorkspaceCalendarsQuery['workspaceCalendars'];
- }
+ if (!gql)
+ return [] satisfies WorkspaceCalendarsQuery['workspace']['calendars'];
const data = await gql({
query: workspaceCalendarsQuery,
variables: { workspaceId: this.workspaceId },
context: { signal },
});
- return data.workspaceCalendars;
+ return data.workspace.calendars;
}
async updateWorkspaceCalendars(items: WorkspaceCalendarItemInput[]) {
@@ -92,16 +79,19 @@ export class CalendarStore extends Store {
signal?: AbortSignal
) {
const gql = this.gql;
- if (!gql) return [] satisfies CalendarEventsQuery['calendarEvents'];
+ if (!gql)
+ return [] satisfies CalendarEventsQuery['workspace']['calendars'][number]['events'];
const data = await gql({
query: calendarEventsQuery,
variables: {
- workspaceCalendarId,
+ workspaceId: this.workspaceId,
from,
to,
},
context: { signal },
});
- return data.calendarEvents;
+ const calendars = data.workspace.calendars;
+ const calendar = calendars.find(item => item.id === workspaceCalendarId);
+ return calendar?.events ?? [];
}
}
diff --git a/packages/frontend/core/src/modules/notification/stores/notification.ts b/packages/frontend/core/src/modules/notification/stores/notification.ts
index 945e74bfc..7cd561ce1 100644
--- a/packages/frontend/core/src/modules/notification/stores/notification.ts
+++ b/packages/frontend/core/src/modules/notification/stores/notification.ts
@@ -60,7 +60,7 @@ export class NotificationStore extends Store {
},
});
- return result.currentUser?.notificationCount;
+ return result.currentUser?.notifications.totalCount;
}
async listNotification(pagination: PaginationInput, signal?: AbortSignal) {
diff --git a/packages/frontend/core/src/modules/permissions/stores/guard.ts b/packages/frontend/core/src/modules/permissions/stores/guard.ts
index 6b0f1fcbd..1a8a93f88 100644
--- a/packages/frontend/core/src/modules/permissions/stores/guard.ts
+++ b/packages/frontend/core/src/modules/permissions/stores/guard.ts
@@ -1,8 +1,8 @@
import {
type GetDocRolePermissionsQuery,
getDocRolePermissionsQuery,
- type GetWorkspaceRolePermissionsQuery,
- getWorkspaceRolePermissionsQuery,
+ type GetWorkspaceInfoQuery,
+ getWorkspaceInfoQuery,
} from '@affine/graphql';
import { Store } from '@toeverything/infra';
@@ -10,7 +10,7 @@ import type { WorkspaceServerService } from '../../cloud';
import type { WorkspaceService } from '../../workspace';
export type WorkspacePermissionActions = keyof Omit<
- GetWorkspaceRolePermissionsQuery['workspaceRolePermissions']['permissions'],
+ GetWorkspaceInfoQuery['workspace']['permissions'],
'__typename'
>;
@@ -34,12 +34,12 @@ export class GuardStore extends Store {
throw new Error('No server');
}
const data = await this.workspaceServerService.server.gql({
- query: getWorkspaceRolePermissionsQuery,
+ query: getWorkspaceInfoQuery,
variables: {
- id: this.workspaceService.workspace.id,
+ workspaceId: this.workspaceService.workspace.id,
},
});
- return data.workspaceRolePermissions.permissions;
+ return data.workspace.permissions;
}
async getDocPermissions(