update websocket
This commit is contained in:
Submodule epess-database updated: 734977b9ad...8be192753e
10
package.json
10
package.json
@@ -133,19 +133,13 @@
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"collectCoverageFrom": ["**/*.(t|j)s"],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
},
|
||||
|
||||
@@ -155,7 +155,7 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
}
|
||||
// build signature
|
||||
const token = this.jwtUtils.signTokenRS256(
|
||||
{ centerId: center.id, email: args.email },
|
||||
JSON.stringify({ centerId: center.id, email: args.email }),
|
||||
'1d',
|
||||
)
|
||||
// build invite url
|
||||
@@ -185,7 +185,7 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
return this.prisma.$transaction(async () => {
|
||||
// sign token
|
||||
const token = this.jwtUtils.signTokenRS256(
|
||||
{ centerId: args.centerId, email: args.email },
|
||||
JSON.stringify({ centerId: args.centerId, email: args.email }),
|
||||
'1d',
|
||||
)
|
||||
// build invite url
|
||||
|
||||
@@ -43,8 +43,10 @@ export class ClerkAuthGuard implements CanActivate {
|
||||
request.user = session.user
|
||||
|
||||
return true
|
||||
} catch (error: any) {
|
||||
throw new UnauthorizedException(error.message)
|
||||
} catch (error: unknown) {
|
||||
throw new UnauthorizedException(
|
||||
error instanceof Error ? error.message : 'Unknown error',
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export class ClerkController {
|
||||
@Post('webhook')
|
||||
@ApiOperation({ summary: 'Clerk Webhook' })
|
||||
@ApiResponse({ status: 200, description: 'Webhook created successfully' })
|
||||
webhook(@Headers() headers: any, @Body() body: any) {
|
||||
webhook(@Headers() headers: Headers, @Body() body: any) {
|
||||
return this.clerkService.webhook(body)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ import { Injectable, Logger } from '@nestjs/common'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { clerkClient } from '@clerk/express'
|
||||
|
||||
export interface ClerkResponse {
|
||||
|
||||
}
|
||||
export interface ClerkResponse {}
|
||||
@Injectable()
|
||||
export class ClerkService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DateTimeResolver, JSONObjectResolver } from 'graphql-scalars'
|
||||
import { JSONObjectResolver } from 'graphql-scalars'
|
||||
import PrismaPlugin, {
|
||||
PothosPrismaDatamodel,
|
||||
PrismaClient,
|
||||
@@ -25,8 +25,7 @@ import { getDatamodel } from '../types/pothos.generated'
|
||||
import { DateTime } from 'luxon'
|
||||
import { Kind } from 'graphql'
|
||||
import { DateTimeUtils } from '../common/utils/datetime.utils'
|
||||
|
||||
// import { rules } from '../common/graphql/common.graphql.auth-rule';
|
||||
import { JsonValue } from '@prisma/client/runtime/library'
|
||||
|
||||
export type SchemaContext =
|
||||
| {
|
||||
@@ -65,8 +64,8 @@ export interface SchemaBuilderOption {
|
||||
Output: string | DateTime | Date
|
||||
}
|
||||
Json: {
|
||||
Input: JSON
|
||||
Output: JSON
|
||||
Input: JsonValue
|
||||
Output: JsonValue
|
||||
}
|
||||
Upload: {
|
||||
Input: FileUpload
|
||||
@@ -161,8 +160,6 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
: parent.totalCount,
|
||||
}),
|
||||
)
|
||||
|
||||
// test print ManagedServiceWhereUniqueInput
|
||||
}
|
||||
}
|
||||
export type BuilderTypes =
|
||||
|
||||
@@ -41,6 +41,7 @@ import { WorkshopSubscriptionModule } from '../WorkshopSubscription/workshopsubs
|
||||
import { initContextCache } from '@pothos/core'
|
||||
import { PubSub } from 'graphql-subscriptions'
|
||||
import { isSubscription } from 'rxjs/internal/Subscription'
|
||||
import { EventEmitter } from 'ws'
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
@@ -147,7 +148,10 @@ import { isSubscription } from 'rxjs/internal/Subscription'
|
||||
},
|
||||
{
|
||||
provide: 'PUB_SUB',
|
||||
useFactory: () => new PubSub(),
|
||||
useFactory: () =>
|
||||
new PubSub({
|
||||
eventEmitter: new EventEmitter({}),
|
||||
}),
|
||||
},
|
||||
],
|
||||
exports: [
|
||||
|
||||
@@ -5,8 +5,10 @@ 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 { Message, MessageContextType, MessageType } from '@prisma/client'
|
||||
import { DateTimeUtils } from 'src/common/utils/datetime.utils'
|
||||
|
||||
@Injectable()
|
||||
export class MessageSchema extends PothosSchema {
|
||||
@@ -31,15 +33,25 @@ export class MessageSchema extends PothosSchema {
|
||||
chatRoomId: t.exposeID('chatRoomId', {
|
||||
description: 'The ID of the chat room.',
|
||||
}),
|
||||
message: t.expose('message', {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
type: 'Json' as any,
|
||||
type: t.expose('type', {
|
||||
type: MessageType,
|
||||
description: 'The type of the message.',
|
||||
}),
|
||||
content: t.exposeString('content', {
|
||||
description: 'The message content.',
|
||||
}),
|
||||
sentAt: t.expose('sentAt', {
|
||||
type: 'DateTime',
|
||||
description: 'The date and time the message was sent.',
|
||||
}),
|
||||
context: t.expose('context', {
|
||||
type: MessageContextType,
|
||||
description: 'The context of the message.',
|
||||
}),
|
||||
metadata: t.expose('metadata', {
|
||||
type: 'Json',
|
||||
description: 'The metadata of the message.',
|
||||
}),
|
||||
sender: t.relation('sender', {
|
||||
description: 'The sender of the message.',
|
||||
}),
|
||||
@@ -95,16 +107,34 @@ export class MessageSchema extends PothosSchema {
|
||||
// mutations
|
||||
this.builder.mutationFields((t) => ({
|
||||
testSendMessage: t.field({
|
||||
type: 'String',
|
||||
type: this.message(),
|
||||
description: 'Test sending a message.',
|
||||
resolve: async (_, __, ctx) => {
|
||||
resolve: async (_root, _args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
ctx.http.pubSub.publish('MESSAGE_SENT', {
|
||||
message: 'Hello, world!',
|
||||
id: '1',
|
||||
senderId: '1',
|
||||
recipientId: '2',
|
||||
chatRoomId: 'b86e840f-81d3-4043-b57a-f9adf719423c',
|
||||
type: MessageType.TEXT,
|
||||
content: 'Hello, world!',
|
||||
context: MessageContextType.CHAT,
|
||||
metadata: {},
|
||||
sentAt: DateTimeUtils.now().toJSDate(),
|
||||
})
|
||||
return 'Message sent'
|
||||
return {
|
||||
id: '1',
|
||||
senderId: '1',
|
||||
recipientId: '2',
|
||||
chatRoomId: 'b86e840f-81d3-4043-b57a-f9adf719423c',
|
||||
type: MessageType.TEXT,
|
||||
content: 'Hello, world!',
|
||||
context: MessageContextType.CHAT,
|
||||
metadata: {},
|
||||
sentAt: DateTimeUtils.now().toJSDate(),
|
||||
}
|
||||
},
|
||||
}),
|
||||
sendMessage: t.prismaField({
|
||||
@@ -112,12 +142,29 @@ export class MessageSchema extends PothosSchema {
|
||||
description: 'Send a message to a chat room.',
|
||||
args: {
|
||||
input: t.arg({
|
||||
type: this.builder.generator.getCreateInput('Message'),
|
||||
type: this.builder.generator.getCreateInput('Message', [
|
||||
'id',
|
||||
'senderId',
|
||||
'sender',
|
||||
'sentAt',
|
||||
]),
|
||||
description: 'The message to send.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
// get the sender from the context and add it to the input
|
||||
args.input.sender = {
|
||||
connect: {
|
||||
id: ctx.http.me?.id,
|
||||
},
|
||||
}
|
||||
if (!args.input.sender) {
|
||||
throw new Error('Cannot get sender from context')
|
||||
}
|
||||
const message = await this.prisma.message.create({
|
||||
...query,
|
||||
data: args.input,
|
||||
@@ -134,24 +181,17 @@ export class MessageSchema extends PothosSchema {
|
||||
this.builder.subscriptionFields((t) => ({
|
||||
messageSent: t.field({
|
||||
description: 'Subscribe to messages sent by users.',
|
||||
args: {},
|
||||
subscribe: async (_, __, ctx) => {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
return (await ctx.websocket.pubSub.asyncIterator(
|
||||
type: this.message(),
|
||||
subscribe: (_, __, ctx: SchemaContext) => {
|
||||
if (!ctx.isSubscription) throw new Error('Not allowed')
|
||||
const {
|
||||
websocket: { pubSub },
|
||||
} = ctx
|
||||
return pubSub.asyncIterator(
|
||||
'MESSAGE_SENT',
|
||||
)) as unknown as AsyncIterable<unknown>
|
||||
) as unknown as AsyncIterable<Message>
|
||||
},
|
||||
type: this.message(), // Add the type property
|
||||
resolve: (payload) =>
|
||||
payload as {
|
||||
message: 'Json'
|
||||
id: string
|
||||
senderId: string
|
||||
chatRoomId: string
|
||||
sentAt: Date
|
||||
},
|
||||
resolve: (payload: Message) => payload,
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
1
src/Message/message.type.ts
Normal file
1
src/Message/message.type.ts
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -57,7 +57,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
description:
|
||||
'Retrieve a list of refund tickets with optional filtering, ordering, and pagination.',
|
||||
args: this.builder.generator.findManyArgs('RefundTicket'),
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
resolve: async (query, _root, args, _ctx, _info) => {
|
||||
return await this.prisma.refundTicket.findMany({
|
||||
...query,
|
||||
where: args.filter ?? undefined,
|
||||
|
||||
@@ -71,8 +71,11 @@ export class UserSchema extends PothosSchema {
|
||||
files: t.relation('files', {
|
||||
description: 'The files of the user.',
|
||||
}),
|
||||
sendingMessage: t.relation('sendingMessage', {
|
||||
description: 'The sending message of the user.',
|
||||
sentMessages: t.relation('sentMessages', {
|
||||
description: 'The sent messages of the user.',
|
||||
}),
|
||||
receivedMessages: t.relation('receivedMessages', {
|
||||
description: 'The received messages of the user.',
|
||||
}),
|
||||
resume: t.relation('resume', {
|
||||
description: 'The resume of the user.',
|
||||
|
||||
@@ -40,7 +40,7 @@ export class WorkshopMeetingRoomSchema extends PothosSchema {
|
||||
workshopMeetingRoom: t.prismaField({
|
||||
type: this.workshopMeetingRoom(),
|
||||
args: this.builder.generator.findUniqueArgs('WorkshopMeetingRoom'),
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
resolve: async (query, _root, args, _ctx, _info) => {
|
||||
return await this.prisma.workshopMeetingRoom.findUnique({
|
||||
...query,
|
||||
where: args.where,
|
||||
@@ -50,7 +50,7 @@ export class WorkshopMeetingRoomSchema extends PothosSchema {
|
||||
workshopMeetingRooms: t.prismaField({
|
||||
type: [this.workshopMeetingRoom()],
|
||||
args: this.builder.generator.findManyArgs('WorkshopMeetingRoom'),
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
resolve: async (query, _root, args, _ctx, _info) => {
|
||||
return await this.prisma.workshopMeetingRoom.findMany({
|
||||
...query,
|
||||
where: args.filter ?? undefined,
|
||||
|
||||
@@ -50,7 +50,7 @@ export class WorkshopSubscriptionSchema extends PothosSchema {
|
||||
args: this.builder.generator.findUniqueArgs('WorkshopSubscription'),
|
||||
description:
|
||||
'Retrieve a single workshop subscription by its unique identifier.',
|
||||
resolve: async (query, root, args) => {
|
||||
resolve: async (query, _root, args) => {
|
||||
return await this.prisma.workshopSubscription.findUnique({
|
||||
...query,
|
||||
where: args.where,
|
||||
@@ -62,7 +62,7 @@ export class WorkshopSubscriptionSchema extends PothosSchema {
|
||||
args: this.builder.generator.findManyArgs('WorkshopSubscription'),
|
||||
description:
|
||||
'Retrieve a list of workshop subscriptions with optional filtering, ordering, and pagination.',
|
||||
resolve: async (query, root, args) => {
|
||||
resolve: async (query, _root, args) => {
|
||||
return await this.prisma.workshopSubscription.findMany({
|
||||
...query,
|
||||
skip: args.skip ?? undefined,
|
||||
|
||||
@@ -134,4 +134,8 @@ export class DateTimeUtils {
|
||||
second: second as SecondNumbers,
|
||||
}
|
||||
}
|
||||
|
||||
static getTimeFromDateTime(dateTime: DateTime): TimeType {
|
||||
return this.toTime(`${dateTime.hour}:${dateTime.minute}:${dateTime.second}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ export class JwtUtils {
|
||||
signToken(payload: string, expiresIn: string) {
|
||||
return sign(payload, process.env.JWT_SECRET!, { expiresIn })
|
||||
}
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
signTokenRS256(payload: any, expiresIn: string) {
|
||||
const privateKey = process.env.JWT_RS256_PRIVATE_KEY!
|
||||
signTokenRS256(payload: string, expiresIn: string) {
|
||||
const privateKey = process.env.JWT_RS256_PRIVATE_KEY
|
||||
if (!privateKey) {
|
||||
throw new Error('JWT_RS256_PRIVATE_KEY is not defined')
|
||||
}
|
||||
return sign(payload, privateKey, {
|
||||
algorithm: 'RS256',
|
||||
expiresIn,
|
||||
@@ -17,7 +19,10 @@ export class JwtUtils {
|
||||
}
|
||||
|
||||
verifyTokenRS256(token: string) {
|
||||
const publicKey = process.env.JWT_RS256_PUBLIC_KEY!
|
||||
const publicKey = process.env.JWT_RS256_PUBLIC_KEY
|
||||
if (!publicKey) {
|
||||
throw new Error('JWT_RS256_PUBLIC_KEY is not defined')
|
||||
}
|
||||
return verify(token, publicKey, {
|
||||
algorithms: ['RS256'],
|
||||
})
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -21,4 +21,4 @@
|
||||
"allowJs": true,
|
||||
"maxNodeModuleJsDepth": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user