import { call } from '@app/common'; import { ensureRatingType } from '@app/server/helpers'; import { IdentityContext } from '@app/server/identity'; import { prisma } from '@app/server/prisma/client'; import { BookChapter as BookChapterSchema, RatingType } from '@generated/types'; import { BookChapter } from '@prisma/client'; import { toBookSchema } from './bookMapper'; export async function toBookChapterSchema( model: BookChapter, { req, res, identity }: IdentityContext ): Promise { return { id: model.id, title: model.title, createdAt: model.createdAt.toISOString(), updatedAt: model.createdAt.toISOString(), foreword: model.foreword, footnote: model.footnote, content: model.content, sequenceNumber: model.sequenceNumber, previousChapterId: await call(async () => { const isFirst = model.sequenceNumber === 1; if (isFirst) return null; const previousChapter = await prisma.bookChapter.findUniqueOrThrow({ where: { bookId_sequenceNumber: { bookId: model.bookId, sequenceNumber: model.sequenceNumber - 1 } }, select: { id: true } }); return previousChapter.id; }), nextChapterId: await call(async () => { const book = await prisma.book.findUniqueOrThrow({ where: { id: model.bookId }, select: { chaptersTotal: true } }); const isLast = model.sequenceNumber === book.chaptersTotal; if (isLast) return null; const nextChapter = await prisma.bookChapter.findUniqueOrThrow({ where: { bookId_sequenceNumber: { bookId: model.bookId, sequenceNumber: model.sequenceNumber + 1 } }, select: { id: true } }); return nextChapter.id; }), reviewsTotal: await call(async () => { const reviewsCount = await prisma.review.count({ where: { bookChapterId: model.id } }); return reviewsCount; }), book: await call(async () => { const book = await prisma.book.findUniqueOrThrow({ where: { id: model.bookId } }); return toBookSchema(book, { req, res, identity }); }), personalRating: await call(async () => { if (identity == null) return RatingType.None; const rating = await prisma.rating.findUnique({ where: { userId_bookChapterId: { userId: identity.id, bookChapterId: model.id } } }); if (rating == null) return RatingType.None; ensureRatingType(rating.type); return rating.type; }) }; }