import { assertUnreachable } from '@app/client/helpers'; 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 { Book as BookSchema, RatingType as RatingTypeSchema, WorkingProgressStatus as WorkingProgressStatusSchema } from '@generated/types'; import { Book, RatingType, WorkingProgressStatus } from '@prisma/client'; import { toUserSchema } from './userMapper'; export async function toBookSchema( model: Book, { identity }: IdentityContext ): Promise { return { id: model.id, title: model.title, description: model.description, author: await call(async () => { const userModel = await prisma.user.findUniqueOrThrow({ where: { id: model.authorId } }); return toUserSchema(userModel); }), createdAt: model.createdAt.toISOString(), updatedAt: model.updatedAt.toISOString(), progressStatus: call(() => { ensureWorkingProgressStatus(model.progressStatus); return model.progressStatus; }), wordsTotal: model.wordsTotal, chaptersTotal: await call(async () => { const chaptersCount = await prisma.bookChapter.count({ where: { bookId: model.id } }); return chaptersCount; }), ratingTotal: await call(async () => { const ratingsUpCount = await prisma.rating.count({ where: { bookId: model.id, type: RatingType.up } }); const ratingsDownCount = await prisma.rating.count({ where: { bookId: model.id, type: RatingType.down } }); return ratingsUpCount - ratingsDownCount; }), reviewsTotal: await call(async () => { const reviewsCount = await prisma.review.count({ where: { bookId: model.id } }); return reviewsCount; }), personalRating: await call(async () => { if (identity == null) return RatingTypeSchema.None; const rating = await prisma.rating.findUnique({ where: { userId_bookId: { userId: identity.id, bookId: model.id } } }); if (rating == null) return RatingTypeSchema.None; ensureRatingType(rating.type); return rating.type; }) }; } function ensureWorkingProgressStatus( value: WorkingProgressStatus ): asserts value is WorkingProgressStatusSchema { if (value === WorkingProgressStatus.inProgress) return; if (value === WorkingProgressStatus.frozen) return; if (value === WorkingProgressStatus.complete) return; assertUnreachable(value); }