diff --git a/compose.yaml b/compose.yaml index 4f59375..b513c6f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -30,6 +30,7 @@ services: - PAYOS_CHECKSUM_KEY=0b82fe148ab98083d471997df5cdd08f3c383013f8bc85e87d7ab1ab4433614e - PAYOS_WEBHOOK_URL=https://api.epess.org/v1/payos/webhook - PAYOS_BASE_URL=https://api-merchant.payos.vn/v2 + - PAYOS_RETURN_URL=https://epess.org/services//checkout - MAILU_FROM=no-reply@mail.epess.org - MAILU_HOST=10.0.27.1 - MAILU_PORT=25 diff --git a/src/Message/message.schema.ts b/src/Message/message.schema.ts index a5e5f9f..7630714 100644 --- a/src/Message/message.schema.ts +++ b/src/Message/message.schema.ts @@ -7,7 +7,12 @@ import { } from '@smatch-corp/nestjs-pothos' import { Builder, SchemaContext } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' -import { Message, MessageContextType, MessageType } from '@prisma/client' +import { + ChatRoomType, + Message, + MessageContextType, + MessageType, +} from '@prisma/client' import { DateTimeUtils } from '../common/utils/datetime.utils' import { PubSubEvent } from '../common/pubsub/pubsub-event' @@ -139,6 +144,25 @@ export class MessageSchema extends PothosSchema { if (!args.input.sender) { throw new Error('Cannot get sender from context') } + let userIds: string[] = [] + // get the recipient if messageContext is CHAT + if (messageContext === MessageContextType.CHAT) { + // get chatRoomId from input + const chatRoomId = args.input.chatRoom?.connect?.id + if (!chatRoomId) { + throw new Error('Cannot get chatRoomId from input') + } + // if chatroom type is SUPPORT, user 1 is mentorId, user 2 is customerId + // query the chatRoom to get the userIds + const chatRoom = await this.prisma.chatRoom.findUnique({ + where: { + id: chatRoomId, + }, + }) + if (chatRoom?.type === ChatRoomType.SUPPORT) { + userIds = [chatRoom.mentorId!, chatRoom.customerId!] + } + } // check if content is empty if (!args.input.content || args.input.content.trim() === '') { throw new Error('Content cannot be empty') @@ -156,6 +180,13 @@ export class MessageSchema extends PothosSchema { `${PubSubEvent.MESSAGE_SENT}.${message.chatRoomId}`, message, ) + // publish to new message subscribers + userIds.forEach((userId: string) => { + ctx.http.pubSub.publish( + `${PubSubEvent.NEW_MESSAGE}.${userId}`, + message, + ) + }) return message }, }), @@ -176,9 +207,9 @@ export class MessageSchema extends PothosSchema { const { websocket: { pubSub }, } = ctx - return pubSub.asyncIterator( + return pubSub.asyncIterator([ `${PubSubEvent.MESSAGE_SENT}.${args.chatRoomId}`, - ) as unknown as AsyncIterable + ]) as unknown as AsyncIterable }, resolve: (payload: Message) => payload, }), diff --git a/src/User/user.module.ts b/src/User/user.module.ts index 4f0856a..c5079d1 100644 --- a/src/User/user.module.ts +++ b/src/User/user.module.ts @@ -1,6 +1,9 @@ import { Module } from '@nestjs/common' import { UserSchema } from './user.schema' +import { MessageModule } from '../Message/message.module' + @Module({ + imports: [MessageModule], providers: [UserSchema], exports: [UserSchema], }) diff --git a/src/User/user.schema.ts b/src/User/user.schema.ts index 6536228..a2b1d7f 100644 --- a/src/User/user.schema.ts +++ b/src/User/user.schema.ts @@ -5,17 +5,21 @@ import { PothosSchema, SchemaBuilderToken, } from '@smatch-corp/nestjs-pothos' -import { Builder } from '../Graphql/graphql.builder' +import { Builder, SchemaContext } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' import { clerkClient } from '@clerk/express' import { UnauthorizedException } from '@nestjs/common' import { MailService } from '../Mail/mail.service' +import { MessageSchema } from 'src/Message/message.schema' +import { Message } from '@prisma/client' +import { PubSubEvent } from 'src/common/pubsub/pubsub-event' @Injectable() export class UserSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, private readonly mailService: MailService, + private readonly messageSchema: MessageSchema, ) { super() } @@ -366,5 +370,22 @@ export class UserSchema extends PothosSchema { }, }), })) + + // Subscription section + this.builder.subscriptionFields((t) => ({ + userScopedMessage: t.field({ + type: this.messageSchema.message(), + subscribe: async (_, _args, ctx: SchemaContext) => { + if (!ctx.isSubscription) throw new Error('Not allowed') + const { + websocket: { pubSub }, + } = ctx + return pubSub.asyncIterator([ + `${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`, + ]) as unknown as AsyncIterable + }, + resolve: async (payload: Message) => payload, + }), + })) } } diff --git a/src/common/pubsub/pubsub-event.ts b/src/common/pubsub/pubsub-event.ts index e8c021c..a4f9739 100644 --- a/src/common/pubsub/pubsub-event.ts +++ b/src/common/pubsub/pubsub-event.ts @@ -1,5 +1,6 @@ export enum PubSubEvent { SERVICE_CREATED = 'SERVICE_CREATED', MESSAGE_SENT = 'MESSAGE_SENT', + NEW_MESSAGE = 'NEW_MESSAGE', NOTIFICATION = 'NOTIFICATION', }