diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index 173ed3ee3..e30ee62f1 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -52,7 +52,7 @@ export type Activity = { export type ActivityCollection = { __typename?: 'ActivityCollection'; cursor?: Maybe; - items?: Maybe>>; + items: Array; totalCount: Scalars['Int']['output']; }; @@ -3867,6 +3867,8 @@ export type Workspace = { createdAt: Scalars['DateTime']['output']; /** Selected fallback when `logo` not set */ defaultLogoIndex: Scalars['Int']['output']; + /** The default role workspace members will receive for workspace projects. */ + defaultProjectRole: Scalars['String']['output']; description?: Maybe; /** Enable/Disable discovery of the workspace */ discoverabilityEnabled: Scalars['Boolean']['output']; @@ -4153,6 +4155,7 @@ export type WorkspaceTeamFilter = { export type WorkspaceUpdateInput = { defaultLogoIndex?: InputMaybe; + defaultProjectRole?: InputMaybe; description?: InputMaybe; discoverabilityEnabled?: InputMaybe; domainBasedMembershipProtectionEnabled?: InputMaybe; @@ -7190,6 +7193,7 @@ export type WorkspaceFieldArgs = { billing: {}, createdAt: {}, defaultLogoIndex: {}, + defaultProjectRole: {}, description: {}, discoverabilityEnabled: {}, domainBasedMembershipProtectionEnabled: {}, diff --git a/packages/server/assets/activitystream/typedefs/activity.graphql b/packages/server/assets/activitystream/typedefs/activity.graphql index 90830b3aa..b684988dc 100644 --- a/packages/server/assets/activitystream/typedefs/activity.graphql +++ b/packages/server/assets/activitystream/typedefs/activity.graphql @@ -121,7 +121,7 @@ extend type Commit { type ActivityCollection { totalCount: Int! cursor: String - items: [Activity] + items: [Activity!]! } type Activity { diff --git a/packages/server/codegen.yml b/packages/server/codegen.yml index 8fcd30f13..44143277f 100644 --- a/packages/server/codegen.yml +++ b/packages/server/codegen.yml @@ -68,6 +68,7 @@ generates: BlobMetadata: '@/modules/blobstorage/domain/types#BlobStorageItem' ServerWorkspacesInfo: '@/modules/core/helpers/graphTypes#GraphQLEmptyReturn' ProjectRole: '@/modules/workspacesCore/helpers/graphTypes#ProjectRoleGraphQLReturn ' + ActivityCollection: '@/modules/activitystream/helpers/graphTypes#ActivityCollectionGraphQLReturn' modules/cross-server-sync/graph/generated/graphql.ts: plugins: - 'typescript' diff --git a/packages/server/modules/activitystream/domain/operations.ts b/packages/server/modules/activitystream/domain/operations.ts index 4f2565dbd..b086849d6 100644 --- a/packages/server/modules/activitystream/domain/operations.ts +++ b/packages/server/modules/activitystream/domain/operations.ts @@ -1,4 +1,8 @@ -import { StreamScopeActivity } from '@/modules/activitystream/helpers/types' +import { StreamActionType } from '@/modules/activitystream/domain/types' +import { + StreamActivityRecord, + StreamScopeActivity +} from '@/modules/activitystream/helpers/types' export type GetActivity = ( streamId: string, @@ -16,3 +20,12 @@ export type GetActiveUserStreams = ( streamIds: string[] }[] > + +export type GetStreamActivity = (args: { + streamId: string + actionType: StreamActionType + after?: Date + before?: Date + cursor?: Date + limit?: number +}) => Promise<{ items: StreamActivityRecord[]; cursor: string | null }> diff --git a/packages/server/modules/activitystream/domain/types.ts b/packages/server/modules/activitystream/domain/types.ts new file mode 100644 index 000000000..aeeb635bf --- /dev/null +++ b/packages/server/modules/activitystream/domain/types.ts @@ -0,0 +1,4 @@ +import { ActionTypes } from '@/modules/activitystream/helpers/types' + +export type StreamActionType = + (typeof ActionTypes.Stream)[keyof (typeof ActionTypes)['Stream']] diff --git a/packages/server/modules/activitystream/errors/activityStream.ts b/packages/server/modules/activitystream/errors/activityStream.ts new file mode 100644 index 000000000..7a181b0ad --- /dev/null +++ b/packages/server/modules/activitystream/errors/activityStream.ts @@ -0,0 +1,7 @@ +import { BaseError } from '@/modules/shared/errors' + +export class InvalidActionTypeError extends BaseError { + static defaultMessage = 'Invalid action type' + static code = 'INVALID_ACTION_TYPE' + static statusCode = 400 +} diff --git a/packages/server/modules/activitystream/graph/resolvers/activity-new.ts b/packages/server/modules/activitystream/graph/resolvers/activity-new.ts new file mode 100644 index 000000000..ded24504a --- /dev/null +++ b/packages/server/modules/activitystream/graph/resolvers/activity-new.ts @@ -0,0 +1,37 @@ +import { db } from '@/db/knex' +import { ActionTypes } from '@/modules/activitystream/helpers/types' +import { getStreamActivityFactory } from '@/modules/activitystream/repositories' +import { getActivityCountByStreamId } from '@/modules/activitystream/services' +import { Resolvers } from '@/modules/core/graph/generated/graphql' +import { InvalidActionTypeError } from '@/modules/activitystream/errors/activityStream' +import { StreamActionType } from '@/modules/activitystream/domain/types' + +export = { + Stream: { + async activity(parent, args) { + if ( + args.actionType && + !Object.values(ActionTypes.Stream).includes(args.actionType as StreamActionType) + ) { + throw new InvalidActionTypeError() + } + + const { items, cursor } = await getStreamActivityFactory({ db })({ + streamId: parent.id, + actionType: (args.actionType as StreamActionType) ?? undefined, + after: args.after ?? undefined, + before: args.before ?? undefined, + cursor: args.cursor ?? undefined, + limit: args.limit ?? undefined + }) + const totalCount = await getActivityCountByStreamId({ + streamId: parent.id, + actionType: args.actionType ?? undefined, + after: args.after ?? undefined, + before: args.before ?? undefined + }) + + return { items, cursor, totalCount } + } + } +} as Resolvers diff --git a/packages/server/modules/activitystream/graph/resolvers/activity.js b/packages/server/modules/activitystream/graph/resolvers/activity.js index 0525a250a..7a76abd99 100644 --- a/packages/server/modules/activitystream/graph/resolvers/activity.js +++ b/packages/server/modules/activitystream/graph/resolvers/activity.js @@ -2,11 +2,9 @@ const { md5 } = require('@/modules/shared/helpers/cryptoHelper') const { getUserActivity, - getStreamActivity, getResourceActivity, getUserTimeline, getActivityCountByResourceId, - getActivityCountByStreamId, getActivityCountByUserId, getTimelineCount } = require('../../services/index') @@ -67,26 +65,6 @@ module.exports = { return await userTimelineQueryCore(parent, args) } }, - Stream: { - async activity(parent, args) { - const { items, cursor } = await getStreamActivity({ - streamId: parent.id, - actionType: args.actionType, - after: args.after, - before: args.before, - cursor: args.cursor, - limit: args.limit - }) - const totalCount = await getActivityCountByStreamId({ - streamId: parent.id, - actionType: args.actionType, - after: args.after, - before: args.before - }) - - return { items, cursor, totalCount } - } - }, Branch: { async activity(parent, args) { diff --git a/packages/server/modules/activitystream/helpers/graphTypes.ts b/packages/server/modules/activitystream/helpers/graphTypes.ts new file mode 100644 index 000000000..55fc47f5f --- /dev/null +++ b/packages/server/modules/activitystream/helpers/graphTypes.ts @@ -0,0 +1,6 @@ +import { StreamActivityRecord } from '@/modules/activitystream/helpers/types' +import { ActivityCollection } from '@/modules/core/graph/generated/graphql' + +export type ActivityCollectionGraphQLReturn = Omit & { + items: StreamActivityRecord[] +} diff --git a/packages/server/modules/activitystream/repositories/index.ts b/packages/server/modules/activitystream/repositories/index.ts index 745f45887..0ef6c935c 100644 --- a/packages/server/modules/activitystream/repositories/index.ts +++ b/packages/server/modules/activitystream/repositories/index.ts @@ -1,5 +1,8 @@ import knex from '@/db/knex' -import { GetActiveUserStreams } from '@/modules/activitystream/domain/operations' +import { + GetActiveUserStreams, + GetStreamActivity +} from '@/modules/activitystream/domain/operations' import { StreamActivityRecord, StreamScopeActivity @@ -54,3 +57,25 @@ export const getActiveUserStreamsFactory = .whereNot('server_acl.role', '=', Roles.Server.ArchivedUser) return (await query) as Awaited> } + +export const getStreamActivityFactory = + ({ db }: { db: Knex }): GetStreamActivity => + async ({ streamId, actionType, after, before, cursor, limit }) => { + if (!limit) { + limit = 200 + } + + const dbQuery = tables.streamActivity(db).where({ streamId }) + if (actionType) dbQuery.andWhere({ actionType }) + if (after) dbQuery.andWhere('time', '>', after) + if (before) dbQuery.andWhere('time', '<', before) + if (cursor) dbQuery.andWhere('time', '<', cursor) + dbQuery.orderBy('time', 'desc').limit(limit) + + const results = await dbQuery.select('*') + + return { + items: results, + cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null + } + } diff --git a/packages/server/modules/activitystream/services/index.js b/packages/server/modules/activitystream/services/index.js index 35f9168b9..01c1ec30b 100644 --- a/packages/server/modules/activitystream/services/index.js +++ b/packages/server/modules/activitystream/services/index.js @@ -64,26 +64,6 @@ module.exports = { } }, - async getStreamActivity({ streamId, actionType, after, before, cursor, limit }) { - if (!limit) { - limit = 200 - } - - const dbQuery = StreamActivity().where({ streamId }) - if (actionType) dbQuery.andWhere({ actionType }) - if (after) dbQuery.andWhere('time', '>', after) - if (before) dbQuery.andWhere('time', '<', before) - if (cursor) dbQuery.andWhere('time', '<', cursor) - dbQuery.orderBy('time', 'desc').limit(limit) - - const results = await dbQuery.select('*') - - return { - items: results, - cursor: results.length > 0 ? results[results.length - 1].time.toISOString() : null - } - }, - async getUserActivity({ userId, actionType, after, before, cursor, limit }) { if (!limit) { limit = 200 diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 336011268..06131ef45 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -9,6 +9,7 @@ import { WorkspaceGraphQLReturn, WorkspaceBillingGraphQLReturn, WorkspaceMutatio import { WebhookGraphQLReturn } from '@/modules/webhooks/helpers/graphTypes'; import { SmartTextEditorValueSchema } from '@/modules/core/services/richTextEditorService'; import { BlobStorageItem } from '@/modules/blobstorage/domain/types'; +import { ActivityCollectionGraphQLReturn } from '@/modules/activitystream/helpers/graphTypes'; import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'; export type Maybe = T | null; export type InputMaybe = Maybe; @@ -64,7 +65,7 @@ export type Activity = { export type ActivityCollection = { __typename?: 'ActivityCollection'; cursor?: Maybe; - items?: Maybe>>; + items: Array; totalCount: Scalars['Int']['output']; }; @@ -4172,7 +4173,6 @@ export type WorkspaceTeamFilter = { export type WorkspaceUpdateInput = { defaultLogoIndex?: InputMaybe; - /** stream:reviewer | stream:contributor */ defaultProjectRole?: InputMaybe; description?: InputMaybe; discoverabilityEnabled?: InputMaybe; @@ -4264,7 +4264,7 @@ export type DirectiveResolverFn; Activity: ResolverTypeWrapper; - ActivityCollection: ResolverTypeWrapper; + ActivityCollection: ResolverTypeWrapper; AddDomainToWorkspaceInput: AddDomainToWorkspaceInput; AdminInviteList: ResolverTypeWrapper & { items: Array }>; AdminQueries: ResolverTypeWrapper; @@ -4308,7 +4308,7 @@ export type ResolversTypes = { BlobMetadata: ResolverTypeWrapper; BlobMetadataCollection: ResolverTypeWrapper & { items?: Maybe> }>; Boolean: ResolverTypeWrapper; - Branch: ResolverTypeWrapper & { author?: Maybe, commits?: Maybe }>; + Branch: ResolverTypeWrapper & { activity?: Maybe, author?: Maybe, commits?: Maybe }>; BranchCollection: ResolverTypeWrapper & { items?: Maybe> }>; BranchCreateInput: BranchCreateInput; BranchDeleteInput: BranchDeleteInput; @@ -4526,7 +4526,7 @@ export type ResolversTypes = { export type ResolversParentTypes = { ActiveUserMutations: MutationsObjectGraphQLReturn; Activity: Activity; - ActivityCollection: ActivityCollection; + ActivityCollection: ActivityCollectionGraphQLReturn; AddDomainToWorkspaceInput: AddDomainToWorkspaceInput; AdminInviteList: Omit & { items: Array }; AdminQueries: GraphQLEmptyReturn; @@ -4567,7 +4567,7 @@ export type ResolversParentTypes = { BlobMetadata: BlobStorageItem; BlobMetadataCollection: Omit & { items?: Maybe> }; Boolean: Scalars['Boolean']['output']; - Branch: Omit & { author?: Maybe, commits?: Maybe }; + Branch: Omit & { activity?: Maybe, author?: Maybe, commits?: Maybe }; BranchCollection: Omit & { items?: Maybe> }; BranchCreateInput: BranchCreateInput; BranchDeleteInput: BranchDeleteInput; @@ -4817,7 +4817,7 @@ export type ActivityResolvers = { cursor?: Resolver, ParentType, ContextType>; - items?: Resolver>>, ParentType, ContextType>; + items?: Resolver, ParentType, ContextType>; totalCount?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index 07a6a76eb..eaab9dc87 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -50,7 +50,7 @@ export type Activity = { export type ActivityCollection = { __typename?: 'ActivityCollection'; cursor?: Maybe; - items?: Maybe>>; + items: Array; totalCount: Scalars['Int']['output']; }; @@ -4158,7 +4158,6 @@ export type WorkspaceTeamFilter = { export type WorkspaceUpdateInput = { defaultLogoIndex?: InputMaybe; - /** stream:reviewer | stream:contributor */ defaultProjectRole?: InputMaybe; description?: InputMaybe; discoverabilityEnabled?: InputMaybe; diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 479b0e7c3..fe82238f3 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -51,7 +51,7 @@ export type Activity = { export type ActivityCollection = { __typename?: 'ActivityCollection'; cursor?: Maybe; - items?: Maybe>>; + items: Array; totalCount: Scalars['Int']['output']; }; @@ -4159,7 +4159,6 @@ export type WorkspaceTeamFilter = { export type WorkspaceUpdateInput = { defaultLogoIndex?: InputMaybe; - /** stream:reviewer | stream:contributor */ defaultProjectRole?: InputMaybe; description?: InputMaybe; discoverabilityEnabled?: InputMaybe;