chore(server): comments IoC 10 - createCommentReplyAndNotifyFactory

This commit is contained in:
Kristaps Fabians Geikins
2024-09-24 13:14:28 +03:00
parent b20807e342
commit afc6477745
7 changed files with 130 additions and 66 deletions
@@ -12,7 +12,7 @@ import { createCommitByBranchId } from '@/modules/core/services/commit/managemen
import { createObject } from '@/modules/core/services/objects'
import { getObject, getStreamObjects } from '@/modules/core/repositories/objects'
import {
createCommentReplyAndNotify,
createCommentReplyAndNotifyFactory,
createCommentThreadAndNotifyFactory
} from '@/modules/comments/services/management'
import {
@@ -24,13 +24,18 @@ import {
getSpecificBranchCommits
} from '@/modules/core/repositories/commits'
import {
getCommentFactory,
insertCommentLinksFactory,
insertCommentsFactory,
markCommentUpdatedFactory,
markCommentViewedFactory
} from '@/modules/comments/repositories/comments'
import { db } from '@/db/knex'
import { CommentsEmitter } from '@/modules/comments/events/emitter'
import { addCommentCreatedActivity } from '@/modules/activitystream/services/commentActivity'
import {
addCommentCreatedActivity,
addReplyAddedActivity
} from '@/modules/activitystream/services/commentActivity'
import { validateInputAttachmentsFactory } from '@/modules/comments/services/commentTextService'
import { getBlobsFactory } from '@/modules/blobstorage/repositories'
@@ -98,6 +103,16 @@ const command: CommandModule<
addCommentCreatedActivity
})
const createCommentReplyAndNotify = createCommentReplyAndNotifyFactory({
getComment: getCommentFactory({ db }),
validateInputAttachments,
insertComments,
insertCommentLinks,
markCommentUpdated: markCommentUpdatedFactory({ db }),
commentsEventsEmit: CommentsEmitter.emit,
addReplyAddedActivity
})
const downloadCommit = downloadCommitFactory({
getStream,
getStreamBranchByName,
@@ -13,13 +13,16 @@ import { createCommitByBranchId } from '@/modules/core/services/commit/managemen
import { createObject } from '@/modules/core/services/objects'
import { getObject, getStreamObjects } from '@/modules/core/repositories/objects'
import {
createCommentReplyAndNotify,
createCommentReplyAndNotifyFactory,
createCommentThreadAndNotifyFactory
} from '@/modules/comments/services/management'
import { createStreamReturnRecord } from '@/modules/core/services/streams/management'
import { createBranchAndNotify } from '@/modules/core/services/branch/management'
import { CommentsEmitter } from '@/modules/comments/events/emitter'
import { addCommentCreatedActivity } from '@/modules/activitystream/services/commentActivity'
import {
addCommentCreatedActivity,
addReplyAddedActivity
} from '@/modules/activitystream/services/commentActivity'
import {
getAllBranchCommits,
getSpecificBranchCommits
@@ -30,8 +33,10 @@ import {
} from '@/modules/core/services/commit/viewerResources'
import { db } from '@/db/knex'
import {
getCommentFactory,
insertCommentLinksFactory,
insertCommentsFactory,
markCommentUpdatedFactory,
markCommentViewedFactory
} from '@/modules/comments/repositories/comments'
import { getBlobsFactory } from '@/modules/blobstorage/repositories'
@@ -93,6 +98,15 @@ const command: CommandModule<
commentsEventsEmit: CommentsEmitter.emit,
addCommentCreatedActivity
})
const createCommentReplyAndNotify = createCommentReplyAndNotifyFactory({
getComment: getCommentFactory({ db }),
validateInputAttachments,
insertComments,
insertCommentLinks,
markCommentUpdated: markCommentUpdatedFactory({ db }),
commentsEventsEmit: CommentsEmitter.emit,
addReplyAddedActivity
})
const downloadProject = downloadProjectFactory({
downloadCommit: downloadCommitFactory({
@@ -7,6 +7,7 @@ import {
import { CommentLinkRecord, CommentRecord } from '@/modules/comments/helpers/types'
import {
CreateCommentInput,
CreateCommentReplyInput,
ViewerUpdateTrackingTarget
} from '@/modules/core/graph/generated/graphql'
import { SmartTextEditorValueSchema } from '@/modules/core/services/richTextEditorService'
@@ -106,3 +107,8 @@ export type CreateCommentThreadAndNotify = (
input: CreateCommentInput,
userId: string
) => Promise<CommentRecord>
export type CreateCommentReplyAndNotify = (
input: CreateCommentReplyInput,
userId: string
) => Promise<CommentRecord>
@@ -57,12 +57,12 @@ import {
getViewerResourceGroupsFactory
} from '@/modules/core/services/commit/viewerResources'
import {
createCommentReplyAndNotify,
editCommentAndNotify,
archiveCommentAndNotify,
authorizeProjectCommentsAccessFactory,
authorizeCommentAccessFactory,
createCommentThreadAndNotifyFactory
createCommentThreadAndNotifyFactory,
createCommentReplyAndNotifyFactory
} from '@/modules/comments/services/management'
import {
isLegacyData,
@@ -184,6 +184,15 @@ const createCommentThreadAndNotify = createCommentThreadAndNotifyFactory({
commentsEventsEmit: CommentsEmitter.emit,
addCommentCreatedActivity
})
const createCommentReplyAndNotify = createCommentReplyAndNotifyFactory({
getComment,
validateInputAttachments,
insertComments,
insertCommentLinks,
markCommentUpdated: markCommentUpdatedFactory({ db }),
commentsEventsEmit: CommentsEmitter.emit,
addReplyAddedActivity
})
const getStreamComment = async (
{ streamId, commentId }: { streamId: string; commentId: string },
@@ -5,9 +5,6 @@ import { getStream } from '@/modules/core/repositories/streams'
import { StreamInvalidAccessError } from '@/modules/core/errors/stream'
import {
getCommentFactory,
insertComment,
insertCommentLinksFactory,
markCommentUpdatedFactory,
updateCommentFactory
} from '@/modules/comments/repositories/comments'
import {
@@ -44,12 +41,14 @@ import { adminOverrideEnabled } from '@/modules/shared/helpers/envHelper'
import { getBlobsFactory } from '@/modules/blobstorage/repositories'
import { db } from '@/db/knex'
import {
CreateCommentReplyAndNotify,
CreateCommentThreadAndNotify,
GetComment,
GetViewerResourceItemsUngrouped,
InsertCommentLinks,
InsertCommentPayload,
InsertComments,
MarkCommentUpdated,
MarkCommentViewed,
ValidateInputAttachments
} from '@/modules/comments/domain/operations'
@@ -205,61 +204,65 @@ export const createCommentThreadAndNotifyFactory =
return comment
}
export async function createCommentReplyAndNotify(
input: CreateCommentReplyInput,
userId: string
) {
const thread = await getCommentFactory({ db })({ id: input.threadId, userId })
if (!thread) {
throw new CommentCreateError('Reply creation failed due to nonexistant thread')
}
await validateInputAttachmentsFactory({ getBlobs: getBlobsFactory({ db }) })(
thread.streamId,
input.content.blobIds || []
)
export const createCommentReplyAndNotifyFactory =
(deps: {
getComment: GetComment
validateInputAttachments: ValidateInputAttachments
insertComments: InsertComments
insertCommentLinks: InsertCommentLinks
markCommentUpdated: MarkCommentUpdated
commentsEventsEmit: CommentsEventsEmit
addReplyAddedActivity: typeof addReplyAddedActivity
}): CreateCommentReplyAndNotify =>
async (input: CreateCommentReplyInput, userId: string) => {
const thread = await deps.getComment({ id: input.threadId, userId })
if (!thread) {
throw new CommentCreateError('Reply creation failed due to nonexistant thread')
}
await deps.validateInputAttachments(thread.streamId, input.content.blobIds || [])
const commentPayload: InsertCommentPayload = {
streamId: thread.streamId,
authorId: userId,
text: buildCommentTextFromInput({
doc: input.content.doc,
blobIds: input.content.blobIds || undefined
}),
parentComment: thread.id,
data: null
}
let reply: CommentRecord
try {
reply = await knex.transaction(async (trx) => {
const reply = await insertComment(commentPayload, { trx })
const links: CommentLinkRecord[] = [
{ resourceType: 'comment', resourceId: thread.id, commentId: reply.id }
]
await insertCommentLinksFactory({ db })(links, { trx })
return reply
})
} catch (e) {
throw new CommentCreateError('Reply creation failed', { cause: ensureError(e) })
}
// Mark parent comment updated and emit events
await Promise.all([
markCommentUpdatedFactory({ db })(thread.id),
CommentsEmitter.emit(CommentsEvents.Created, {
comment: reply
}),
addReplyAddedActivity({
const commentPayload: InsertCommentPayload = {
streamId: thread.streamId,
input,
reply,
userId
})
])
authorId: userId,
text: buildCommentTextFromInput({
doc: input.content.doc,
blobIds: input.content.blobIds || undefined
}),
parentComment: thread.id,
data: null
}
return reply
}
let reply: CommentRecord
try {
reply = await knex.transaction(async (trx) => {
const [reply] = await deps.insertComments([commentPayload], { trx })
const links: CommentLinkRecord[] = [
{ resourceType: 'comment', resourceId: thread.id, commentId: reply.id }
]
await deps.insertCommentLinks(links, { trx })
return reply
})
} catch (e) {
throw new CommentCreateError('Reply creation failed', { cause: ensureError(e) })
}
// Mark parent comment updated and emit events
await Promise.all([
deps.markCommentUpdated(thread.id),
deps.commentsEventsEmit(CommentsEvents.Created, {
comment: reply
}),
deps.addReplyAddedActivity({
streamId: thread.streamId,
input,
reply,
userId
})
])
return reply
}
export async function editCommentAndNotify(input: EditCommentInput, userId: string) {
const comment = await getCommentFactory({ db })({ id: input.commentId, userId })
@@ -1,16 +1,21 @@
import { db } from '@/db/knex'
import { moduleLogger, crossServerSyncLogger } from '@/logging/logging'
import { addCommentCreatedActivity } from '@/modules/activitystream/services/commentActivity'
import {
addCommentCreatedActivity,
addReplyAddedActivity
} from '@/modules/activitystream/services/commentActivity'
import { getBlobsFactory } from '@/modules/blobstorage/repositories'
import { CommentsEmitter } from '@/modules/comments/events/emitter'
import {
getCommentFactory,
insertCommentLinksFactory,
insertCommentsFactory,
markCommentUpdatedFactory,
markCommentViewedFactory
} from '@/modules/comments/repositories/comments'
import { validateInputAttachmentsFactory } from '@/modules/comments/services/commentTextService'
import {
createCommentReplyAndNotify,
createCommentReplyAndNotifyFactory,
createCommentThreadAndNotifyFactory
} from '@/modules/comments/services/management'
import {
@@ -73,6 +78,16 @@ const crossServerSyncModule: SpeckleModule = {
commentsEventsEmit: CommentsEmitter.emit,
addCommentCreatedActivity
})
const createCommentReplyAndNotify = createCommentReplyAndNotifyFactory({
getComment: getCommentFactory({ db }),
validateInputAttachments,
insertComments,
insertCommentLinks,
markCommentUpdated: markCommentUpdatedFactory({ db }),
commentsEventsEmit: CommentsEmitter.emit,
addReplyAddedActivity
})
const ensureOnboardingProject = ensureOnboardingProjectFactory({
getOnboardingBaseStream,
getFirstAdmin,
@@ -14,7 +14,6 @@ import { createCommitByBranchId } from '@/modules/core/services/commit/managemen
import { getUser } from '@/modules/core/repositories/users'
import type { SpeckleViewer } from '@speckle/shared'
import { retry } from '@speckle/shared'
import { createCommentReplyAndNotify } from '@/modules/comments/services/management'
import {
createApolloClient,
assertValidGraphQLResult
@@ -28,7 +27,10 @@ import {
CrossSyncProjectViewerResourcesQuery
} from '@/modules/cross-server-sync/graph/generated/graphql'
import { DownloadCommit } from '@/modules/cross-server-sync/domain/operations'
import { CreateCommentThreadAndNotify } from '@/modules/comments/domain/operations'
import {
CreateCommentReplyAndNotify,
CreateCommentThreadAndNotify
} from '@/modules/comments/domain/operations'
type LocalResources = Awaited<ReturnType<ReturnType<typeof getLocalResourcesFactory>>>
type LocalResourcesWithCommit = LocalResources & { newCommitId: string }
@@ -370,7 +372,7 @@ const cleanViewerState = (
type SaveNewThreadsDeps = {
createCommentThreadAndNotify: CreateCommentThreadAndNotify
createCommentReplyAndNotify: typeof createCommentReplyAndNotify
createCommentReplyAndNotify: CreateCommentReplyAndNotify
}
const saveNewThreadsFactory =