Files
speckle-server/packages/server/modules/activitystream/graph/resolvers/activity.ts
T
Kristaps Fabians Geikins bde148f286 chore(server): migrating fully to ESM (#5042)
* wip

* some extra fixes

* stuff kinda works?

* need to figure out mocks

* need to figure out mocks

* fix db listener

* gqlgen fix

* minor gqlgen watch adjustment

* lint fixes

* delete old codegen file

* converting migrations to ESM

* getModuleDIrectory

* vitest sort of works

* added back ts-vitest

* resolve gql double load

* fixing test timeout configs

* TSC lint fix

* fix automate tests

* moar debugging

* debugging

* more debugging

* codegen update

* server works

* yargs migrated

* chore(server): getting rid of global mocks for Server ESM (#5046)

* got rid of email mock

* got rid of comment mocks

* got rid of multi region mocks

* got rid of stripe mock

* admin override mock updated

* removed final mock

* fixing import.meta.resolve calls

* another import.meta.resolve fix

* added requested test

* nyc ESM fix

* removed unneeded deps + linting

* yarn lock forgot to commit

* tryna fix flakyness

* email capture util fix

* sendEmail fix

* fix TSX check

* sender transporter fix + CR comments

* merge main fix

* test fixx

* circleci fix

* gqlgen bigint fix

* error formatter fix

* more error formatting improvements

* esmloader added to Dockerfile

* more dockerfile fixes

* bg jobs fix
2025-07-14 10:26:19 +03:00

176 lines
5.3 KiB
TypeScript

import { db } from '@/db/knex'
import { StreamActionTypes } from '@/modules/activitystream/helpers/types'
import {
getActivityCountByResourceIdFactory,
getActivityCountByStreamIdFactory,
getActivityCountByUserIdFactory,
getResourceActivityFactory,
getStreamActivityFactory,
getTimelineCountFactory,
getUserActivityFactory,
getUserTimelineFactory
} from '@/modules/activitystream/repositories'
import { Resolvers } from '@/modules/core/graph/generated/graphql'
import { InvalidActionTypeError } from '@/modules/activitystream/errors/activityStream'
import { StreamActionType } from '@/modules/activitystream/domain/types'
import { md5 } from '@/modules/shared/helpers/cryptoHelper'
type ActivityPaginatedArgs = {
actionType?: string | null
after?: Date | null
before?: Date | null
cursor?: Date | null
limit?: number // This field is required because the type-defs defines it as required
}
const userActivityQueryCore = async (
parent: { id: string },
args: ActivityPaginatedArgs
) => {
const { items, cursor } = await getUserActivityFactory({ db })({
userId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined,
cursor: args.cursor ?? undefined,
limit: args.limit
})
const totalCount = await getActivityCountByUserIdFactory({ db })({
userId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined
})
return { items, cursor, totalCount }
}
const userTimelineQueryCore = async (
parent: { id: string },
args: ActivityPaginatedArgs
) => {
const { items, cursor } = await getUserTimelineFactory({ db })({
userId: parent.id,
after: args.after ?? undefined,
before: args.before ?? undefined,
cursor: args.cursor ?? undefined,
limit: args.limit
})
const totalCount = await getTimelineCountFactory({ db })({
userId: parent.id,
after: args.after ?? undefined,
before: args.before ?? undefined
})
return { items, cursor, totalCount }
}
export default {
LimitedUser: {
async activity(parent, args) {
return await userActivityQueryCore(parent, args)
},
async timeline(parent, args) {
return await userTimelineQueryCore(parent, args)
}
},
User: {
async activity(parent, args) {
return await userActivityQueryCore(parent, args)
},
async timeline(parent, args) {
return await userTimelineQueryCore(parent, args)
}
},
Stream: {
async activity(parent, args) {
if (
args.actionType &&
!Object.values(StreamActionTypes.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 getActivityCountByStreamIdFactory({ db })({
streamId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined
})
return { items, cursor, totalCount }
}
},
Commit: {
async activity(parent, args) {
const { items, cursor } = await getResourceActivityFactory({ db })({
resourceType: 'commit',
resourceId: 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 getActivityCountByResourceIdFactory({ db })({
resourceId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined
})
return { items, cursor, totalCount }
}
},
Branch: {
async activity(parent, args) {
const { items, cursor } = await getResourceActivityFactory({ db })({
resourceType: 'branch',
resourceId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined,
cursor: args.cursor ?? undefined,
limit: args.limit
})
const totalCount = await getActivityCountByResourceIdFactory({ db })({
resourceId: parent.id,
actionType: (args.actionType as StreamActionType) ?? undefined,
after: args.after ?? undefined,
before: args.before ?? undefined
})
return { items, cursor, totalCount }
}
},
Activity: {
/**
* We need a unique ID to be able to properly cache stuff on the clientside
*/
id(parent) {
if (!parent) return null
const { streamId, resourceId, userId, time } = parent
const plainIdentity = JSON.stringify({
streamId,
resourceId,
userId,
time
})
return md5(plainIdentity)
}
}
} as Resolvers