import { Inject, Injectable } from '@nestjs/common'; import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken, } from '@smatch-corp/nestjs-pothos'; import { Builder } from '../Graphql/graphql.builder'; import { PrismaService } from '../Prisma/prisma.service'; import { MinioService } from '../Minio/minio.service'; @Injectable() export class ResumeSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, private readonly minioService: MinioService, ) { super(); } @PothosRef() resume() { return this.builder.prismaObject('Resume', { fields: (t) => ({ id: t.exposeID('id'), userId: t.exposeID('userId'), centerId: t.exposeID('centerId'), status: t.exposeString('status'), createdAt: t.expose('createdAt', { type: 'DateTime', nullable: true, }), updatedAt: t.expose('updatedAt', { type: 'DateTime', nullable: true, }), center: t.relation('center'), resumeFile: t.relation('ResumeFile'), }), }); } @PothosRef() resumeFile() { return this.builder.prismaObject('ResumeFile', { fields: (t) => ({ id: t.exposeID('id'), resumeId: t.exposeID('resumeId'), fileUrl: t.exposeString('fileUrl'), type: t.exposeString('type'), createdAt: t.expose('createdAt', { type: 'DateTime', nullable: true, }), updatedAt: t.expose('updatedAt', { type: 'DateTime', nullable: true, }), resume: t.relation('resume'), }), }); } @Pothos() init(): void { this.builder.queryFields((t) => ({ resumes: t.prismaField({ type: [this.resume()], args: this.builder.generator.findManyArgs('Resume'), resolve: async (query, root, args) => { return await this.prisma.resume.findMany({ ...query, skip: args.skip ?? undefined, take: args.take ?? 10, orderBy: args.orderBy ?? undefined, where: args.filter ?? undefined, }); }, }), resume: t.prismaField({ type: this.resume(), args: this.builder.generator.findUniqueArgs('Resume'), resolve: async (query, root, args) => { const resume = await this.prisma.resume.findUnique({ ...query, where: args.where, }); return resume; }, }), resumeFile: t.prismaField({ type: this.resumeFile(), args: this.builder.generator.findUniqueArgs('ResumeFile'), resolve: async (query, root, args) => { const resumeFile = await this.prisma.resumeFile.findUnique({ ...query, where: args.where, }); if (!resumeFile) { return null; } const resumeFileUrl = await this.minioService.getFileUrl( resumeFile.fileUrl, 'resumes', ); resumeFile.fileUrl = resumeFileUrl; return resumeFile; }, }), resumeFiles: t.prismaField({ type: [this.resumeFile()], args: this.builder.generator.findManyArgs('ResumeFile'), resolve: async (query, root, args) => { const resumeFiles = await this.prisma.resumeFile.findMany({ ...query, skip: args.skip ?? undefined, take: args.take ?? 10, orderBy: args.orderBy ?? undefined, where: args.filter ?? undefined, }); const resumeFilesWithUrl = await Promise.all( resumeFiles.map(async (resumeFile) => { const resumeFileUrl = await this.minioService.getFileUrl( resumeFile.fileUrl, 'resumes', ); return { ...resumeFile, fileUrl: resumeFileUrl }; }), ); return resumeFilesWithUrl; }, }), })); // Mutations section this.builder.mutationFields((t) => ({ upsertResume: t.prismaField({ type: this.resume(), args: { resumeFile: t.arg({ type: 'Upload', required: true, }), centerId: t.arg({ type: 'String', required: true, }), userId: t.arg({ type: 'String', required: true, }), }, resolve: async (query, root, args) => { const { resumeFile } = args; const { mimetype } = await resumeFile; const { filename } = await this.minioService.uploadFile( resumeFile, 'resumes', ); const fileUrl = await this.minioService.getFileUrl( filename, 'resumes', ); const { userId, centerId } = args; const resume = await this.prisma.resume.upsert({ ...query, where: { userId_centerId: { userId, centerId, }, }, create: { userId, centerId, ResumeFile: { create: { fileUrl, type: mimetype, }, }, }, update: { ResumeFile: { create: { fileUrl, type: mimetype, }, }, }, }); // get last resume file const lastResumeFile = await this.prisma.resumeFile.findFirst({ where: { resumeId: resume.id, }, orderBy: { createdAt: 'desc', }, }); return { ...resume, resumeFile: lastResumeFile }; }, }), })); } }