mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 18:02:47 +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:
@@ -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) {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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<AccessToken[]> {
|
||||
return await this.models.accessToken.list(user.id);
|
||||
}
|
||||
|
||||
@Query(() => [RevealedAccessToken])
|
||||
@Query(() => [RevealedAccessToken], {
|
||||
deprecationReason: 'use currentUser.revealedAccessTokens',
|
||||
})
|
||||
async revealedAccessTokens(
|
||||
@CurrentUser() user: CurrentUser
|
||||
): Promise<RevealedAccessToken[]> {
|
||||
@@ -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<AccessToken[]> {
|
||||
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<RevealedAccessToken[]> {
|
||||
if (!currentUser || currentUser.id !== user.id) {
|
||||
throw new ActionForbidden();
|
||||
}
|
||||
return await this.models.accessToken.list(user.id, true);
|
||||
}
|
||||
}
|
||||
|
||||
22
packages/backend/server/src/core/access-token/types.ts
Normal file
22
packages/backend/server/src/core/access-token/types.ts
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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<AppConfigValidateResult[]> {
|
||||
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<AppConfigValidateResult[]> {
|
||||
return this.validateConfigInternal(updates);
|
||||
}
|
||||
|
||||
private validateConfigInternal(
|
||||
updates: UpdateAppConfigInput[]
|
||||
): AppConfigValidateResult[] {
|
||||
const errors = this.service.validateConfig(updates);
|
||||
|
||||
return updates.map(update => {
|
||||
|
||||
@@ -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<BlobUploadPart> {
|
||||
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<BlobUploadPart> {
|
||||
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<BlobUploadPart> {
|
||||
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,
|
||||
|
||||
@@ -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],
|
||||
})
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<string> {
|
||||
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<string> {
|
||||
return this.applyDocUpdatesInternal(user, workspaceId, docId, op, updates);
|
||||
}
|
||||
|
||||
private async applyDocUpdatesInternal(
|
||||
user: CurrentUser,
|
||||
workspaceId: string,
|
||||
docId: string,
|
||||
op: string,
|
||||
updates: string
|
||||
): Promise<string> {
|
||||
await this.assertPermission(user, { workspaceId, docId });
|
||||
|
||||
|
||||
@@ -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}`,
|
||||
|
||||
@@ -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!
|
||||
|
||||
Reference in New Issue
Block a user