mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-07 01:09:54 +08:00
feat: reduce backend (#14251)
#### PR Dependency Tree * **PR #14251** 👈 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** * 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. <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:
@@ -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,
|
||||
|
||||
+5
-3
@@ -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 ||
|
||||
|
||||
+4
-3
@@ -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<CalendarAccountsQuery['currentUser']>['calendarAccounts'][number]
|
||||
>['calendars'][number];
|
||||
|
||||
export const SubscriptionSetting = ({
|
||||
subscription,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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<UserSettings | undefined> {
|
||||
const result = await this.gqlService.gql({
|
||||
query: getUserSettingsQuery,
|
||||
query: getCurrentUserProfileQuery,
|
||||
});
|
||||
return result.currentUser?.settings;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type {
|
||||
CalendarAccountCalendarsQuery,
|
||||
CalendarAccountsQuery,
|
||||
CalendarEventsQuery,
|
||||
WorkspaceCalendarItemInput,
|
||||
@@ -16,20 +15,29 @@ export class CalendarIntegration extends Entity {
|
||||
super();
|
||||
}
|
||||
|
||||
accounts$ = new LiveData<CalendarAccountsQuery['calendarAccounts'][number][]>(
|
||||
[]
|
||||
);
|
||||
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<string, CalendarEventsQuery['calendarEvents'][number][]>
|
||||
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;
|
||||
|
||||
@@ -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 ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class NotificationStore extends Store {
|
||||
},
|
||||
});
|
||||
|
||||
return result.currentUser?.notificationCount;
|
||||
return result.currentUser?.notifications.totalCount;
|
||||
}
|
||||
|
||||
async listNotification(pagination: PaginationInput, signal?: AbortSignal) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user