mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-06 11:59:51 +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:
@@ -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