refactor(trpc): centralize pet-identity select fragments in a repository layer
The Prisma select fragment { id, name, nickname, avatarKey } (and its
isVerified + owner-sponsor extension) was copy-pasted ~38x across 13
router files -- no repository/query layer existed to consolidate it
(Gitea #31 DRY audit).
Adds src/repositories/pet-repository.ts exporting petIdentitySelect and
petCardSelect (composed via spread) plus their inferred Prisma payload
types, and migrates every call site to import and reuse them -- either
directly or composed with the few extra fields a given query needs
(e.g. ownerId, bio, isVerified where the base fragment doesn't cover
it). A handful of structurally different, smaller field selections
(e.g. name+nickname only, no id) were deliberately left as-is rather
than force-fit into the shared shape.
Pure refactor, no behavior change -- verified via tsc, vitest, and a
production build.
This commit is contained in:
1 parent
1f177c5e88
commit
e0c887c71c
14 files changed
+78
-74
No files matched your search
@@ -0,0 +1,27 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
/**
|
||||
* Minimal pet identity — id/name/nickname/avatarKey. This is the shape every
|
||||
* "who posted/commented/follows this" display needs; compose on top of it
|
||||
* (spread + extra fields) rather than hand-writing the fragment again.
|
||||
*/
|
||||
export const petIdentitySelect = {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
} satisfies Prisma.PetSelect;
|
||||
|
||||
/**
|
||||
* Pet identity plus the fields a feed/explore/profile card renders alongside
|
||||
* the name: the verified checkmark and the owner's sponsor window (consumed
|
||||
* via isActiveSponsor() in src/lib/sponsor.ts).
|
||||
*/
|
||||
export const petCardSelect = {
|
||||
...petIdentitySelect,
|
||||
isVerified: true,
|
||||
owner: { select: { sponsorSince: true, sponsorPeriodEnd: true } },
|
||||
} satisfies Prisma.PetSelect;
|
||||
|
||||
export type PetIdentity = Prisma.PetGetPayload<{ select: typeof petIdentitySelect }>;
|
||||
export type PetCardIdentity = Prisma.PetGetPayload<{ select: typeof petCardSelect }>;
|
||||
+12
-14
@@ -5,6 +5,7 @@ import { TRPCError } from "@trpc/server";
|
||||
import { AdminRoleType, BlacklistEntryType, type PrismaClient, type ReportReason } from "@prisma/client";
|
||||
import { clerkClient } from "@clerk/nextjs/server";
|
||||
import { router, protectedProcedure } from "@/trpc/init";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
import {
|
||||
createSignedUploadUrl,
|
||||
ALLOWED_CONTENT_TYPES,
|
||||
@@ -291,7 +292,7 @@ export const adminRouter = router({
|
||||
}
|
||||
: undefined,
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true, ownerId: true } },
|
||||
pet: { select: { ...petIdentitySelect, ownerId: true } },
|
||||
images: { orderBy: { position: "asc" }, take: 1 },
|
||||
videoPost: { select: { muxPlaybackId: true } },
|
||||
milestone: true,
|
||||
@@ -557,7 +558,7 @@ export const adminRouter = router({
|
||||
await assertAdmin(ctx.prisma, ctx.userId);
|
||||
return ctx.prisma.comment.findMany({
|
||||
where: { postId: input.postId },
|
||||
include: { pet: { select: { id: true, name: true, nickname: true, avatarKey: true } } },
|
||||
include: { pet: { select: petIdentitySelect } },
|
||||
orderBy: { createdAt: "asc" },
|
||||
});
|
||||
}),
|
||||
@@ -632,7 +633,7 @@ export const adminRouter = router({
|
||||
...(input.role !== "all" && input.role !== "none" ? { adminRole: { role: input.role } } : {}),
|
||||
},
|
||||
include: {
|
||||
pets: { select: { id: true, name: true, nickname: true, avatarKey: true, isVerified: true }, take: 3 },
|
||||
pets: { select: { ...petIdentitySelect, isVerified: true }, take: 3 },
|
||||
ban: true,
|
||||
shadowban: true,
|
||||
adminRole: true,
|
||||
@@ -862,10 +863,7 @@ export const adminRouter = router({
|
||||
include: {
|
||||
pet: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
...petIdentitySelect,
|
||||
isVerified: true,
|
||||
ownerId: true,
|
||||
bio: true,
|
||||
@@ -1061,8 +1059,8 @@ export const adminRouter = router({
|
||||
const convs = await ctx.prisma.conversation.findMany({
|
||||
where: { OR: [{ petAId: teamPet.id }, { petBId: teamPet.id }] },
|
||||
include: {
|
||||
petA: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
petB: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
petA: { select: petIdentitySelect },
|
||||
petB: { select: petIdentitySelect },
|
||||
messages: { orderBy: { createdAt: "desc" }, take: 1 },
|
||||
_count: {
|
||||
select: { messages: { where: { senderPetId: { not: teamPet.id }, readAt: null } } },
|
||||
@@ -1096,7 +1094,7 @@ export const adminRouter = router({
|
||||
where: { conversationId: input.conversationId },
|
||||
orderBy: { createdAt: "asc" },
|
||||
take: 200,
|
||||
include: { senderPet: { select: { id: true, name: true, nickname: true, avatarKey: true } } },
|
||||
include: { senderPet: { select: petIdentitySelect } },
|
||||
});
|
||||
|
||||
// Fire-and-forget — any admin opening the thread marks it read for the whole team.
|
||||
@@ -1199,7 +1197,7 @@ export const adminRouter = router({
|
||||
|
||||
const reports = await ctx.prisma.report.findMany({
|
||||
include: {
|
||||
reporter: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
reporter: { select: petIdentitySelect },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 100,
|
||||
@@ -1220,7 +1218,7 @@ export const adminRouter = router({
|
||||
createdAt: true,
|
||||
reactionCount: true,
|
||||
commentCount: true,
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
images: {
|
||||
orderBy: { position: "asc" },
|
||||
take: 4,
|
||||
@@ -1263,7 +1261,7 @@ export const adminRouter = router({
|
||||
type: true,
|
||||
createdAt: true,
|
||||
hiddenAt: true,
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
images: {
|
||||
orderBy: { position: "asc" },
|
||||
select: { storageKey: true, position: true, blurhash: true },
|
||||
@@ -1272,7 +1270,7 @@ export const adminRouter = router({
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 200,
|
||||
select: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import "server-only";
|
||||
import { z } from "zod";
|
||||
import { router, protectedProcedure } from "@/trpc/init";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
export const adsRouter = router({
|
||||
// Returns view/reaction/comment/repost counts + whether the given pet has interacted
|
||||
@@ -91,7 +92,7 @@ export const adsRouter = router({
|
||||
return ctx.prisma.adComment.findMany({
|
||||
where: { adId: input.adId },
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
orderBy: { createdAt: "asc" },
|
||||
take: 100,
|
||||
@@ -113,7 +114,7 @@ export const adsRouter = router({
|
||||
ctx.prisma.adComment.create({
|
||||
data: { adId: input.adId, petId: input.petId, body: input.body },
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
}),
|
||||
ctx.prisma.advertisement.update({
|
||||
|
||||
@@ -5,6 +5,7 @@ import { router, protectedProcedure, rateLimited } from "@/trpc/init";
|
||||
import { createMentionNotifications } from "@/lib/mention-helpers";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { notify } from "@/lib/notify";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
export const commentsRouter = router({
|
||||
create: protectedProcedure
|
||||
@@ -27,7 +28,7 @@ export const commentsRouter = router({
|
||||
body: input.body,
|
||||
},
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
}),
|
||||
ctx.prisma.post.update({
|
||||
@@ -77,7 +78,7 @@ export const commentsRouter = router({
|
||||
orderBy: { createdAt: "asc" },
|
||||
take: input.limit + 1,
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { router, publicProcedure, rateLimited } from "@/trpc/init";
|
||||
import { pickLocalizedName } from "@/lib/localized-name";
|
||||
import { getSpiderExclusionId } from "@/lib/spider-exclusion";
|
||||
import { petCardSelect } from "@/repositories/pet-repository";
|
||||
|
||||
const TRENDING_POSTS_WINDOW_MS = 48 * 60 * 60 * 1000; // 48 h
|
||||
const TRENDING_HASHTAGS_WINDOW_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
||||
@@ -75,16 +76,7 @@ export const exploreRouter = router({
|
||||
},
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
isVerified: true,
|
||||
owner: { select: { sponsorSince: true, sponsorPeriodEnd: true } },
|
||||
},
|
||||
},
|
||||
pet: { select: petCardSelect },
|
||||
milestone: true,
|
||||
},
|
||||
orderBy: [{ pinnedAt: { sort: "desc", nulls: "last" } }, { reactionCount: "desc" }],
|
||||
|
||||
@@ -6,6 +6,7 @@ import { redis } from "@/lib/redis";
|
||||
import { getFeedPage } from "@/lib/feed-helpers";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { getSpiderExclusionId } from "@/lib/spider-exclusion";
|
||||
import { petCardSelect } from "@/repositories/pet-repository";
|
||||
|
||||
// Engagement-based ranking score for the algorithmic feed.
|
||||
// Recency decays logarithmically; reaction/comment/repost weights are tuned
|
||||
@@ -27,16 +28,7 @@ function algoScore(
|
||||
}
|
||||
|
||||
const postInclude = {
|
||||
pet: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
isVerified: true,
|
||||
owner: { select: { sponsorSince: true, sponsorPeriodEnd: true } },
|
||||
},
|
||||
},
|
||||
pet: { select: petCardSelect },
|
||||
images: { orderBy: { position: "asc" } as const },
|
||||
milestone: true,
|
||||
videoPost: { select: { status: true, muxPlaybackId: true } },
|
||||
@@ -44,16 +36,7 @@ const postInclude = {
|
||||
include: {
|
||||
originalPost: {
|
||||
include: {
|
||||
pet: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
isVerified: true,
|
||||
owner: { select: { sponsorSince: true, sponsorPeriodEnd: true } },
|
||||
},
|
||||
},
|
||||
pet: { select: petCardSelect },
|
||||
images: { orderBy: { position: "asc" } as const },
|
||||
milestone: true,
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@ import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { notify } from "@/lib/notify";
|
||||
import { FOLLOWER_MILESTONE_THRESHOLDS as FOLLOWER_MILESTONES } from "@/lib/milestone-thresholds";
|
||||
import { pickLocalizedName } from "@/lib/localized-name";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
/**
|
||||
* Follows tRPC router — pet-to-pet social graph (SOCL-01, SOCL-02, SOCL-03).
|
||||
@@ -83,7 +84,7 @@ export const followsRouter = router({
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
milestone: true,
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -174,10 +175,7 @@ export const followsRouter = router({
|
||||
include: {
|
||||
follower: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
...petIdentitySelect,
|
||||
species: { select: { name: true, translations: { where: { locale: ctx.locale } } } },
|
||||
},
|
||||
},
|
||||
@@ -221,7 +219,7 @@ export const followsRouter = router({
|
||||
},
|
||||
},
|
||||
select: {
|
||||
followee: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
followee: { select: petIdentitySelect },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 100,
|
||||
@@ -252,10 +250,7 @@ export const followsRouter = router({
|
||||
include: {
|
||||
followee: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
nickname: true,
|
||||
avatarKey: true,
|
||||
...petIdentitySelect,
|
||||
species: { select: { name: true, translations: { where: { locale: ctx.locale } } } },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import { router, protectedProcedure, rateLimited } from "@/trpc/init";
|
||||
import type { PrismaClient } from "@prisma/client";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { notify } from "@/lib/notify";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
/**
|
||||
* Messages tRPC router — Phase 6 Direct Messages.
|
||||
@@ -50,8 +51,8 @@ export const conversationsRouter = router({
|
||||
const convs = await ctx.prisma.conversation.findMany({
|
||||
where: { OR: [{ petAId: input.petId }, { petBId: input.petId }] },
|
||||
include: {
|
||||
petA: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
petB: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
petA: { select: petIdentitySelect },
|
||||
petB: { select: petIdentitySelect },
|
||||
messages: {
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 1,
|
||||
@@ -188,7 +189,7 @@ export const messagesRouter = router({
|
||||
orderBy: { createdAt: "asc" },
|
||||
take: input.limit + 1,
|
||||
include: {
|
||||
senderPet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
senderPet: { select: petIdentitySelect },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -237,7 +238,7 @@ export const messagesRouter = router({
|
||||
senderPetId: input.senderPetId,
|
||||
body: input.body,
|
||||
},
|
||||
include: { senderPet: { select: { id: true, name: true, nickname: true, avatarKey: true } } },
|
||||
include: { senderPet: { select: petIdentitySelect } },
|
||||
}),
|
||||
// Touch conversation updatedAt so inbox re-orders correctly
|
||||
ctx.prisma.conversation.update({
|
||||
|
||||
@@ -5,6 +5,7 @@ import { redis } from "@/lib/redis";
|
||||
import { fanOutPost } from "@/lib/feed-helpers";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { USER_INITIATED_MILESTONE_TYPES } from "@/lib/milestone-meta";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
/**
|
||||
* Milestones tRPC router — structured milestone posts (MILE-01, MILE-02).
|
||||
@@ -66,7 +67,7 @@ export const milestonesRouter = router({
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
milestone: true,
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -97,7 +98,7 @@ export const milestonesRouter = router({
|
||||
include: {
|
||||
milestone: true,
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: input.limit,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { router, protectedProcedure } from "@/trpc/init";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
const PAGE_SIZE = 30;
|
||||
|
||||
@@ -26,7 +27,7 @@ export const notificationsRouter = router({
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: input.limit + 1,
|
||||
include: {
|
||||
actorPet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
actorPet: { select: petIdentitySelect },
|
||||
post: { select: { id: true, petId: true, images: { take: 1, orderBy: { position: "asc" } } } },
|
||||
comment: { select: { id: true, body: true } },
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import { router, protectedProcedure } from "@/trpc/init";
|
||||
import { generateInviteCode, INVITE_CODES_PER_USER } from "@/lib/invite-codes";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { pickLocalizedName } from "@/lib/localized-name";
|
||||
import { petCardSelect } from "@/repositories/pet-repository";
|
||||
|
||||
export const petsRouter = router({
|
||||
/**
|
||||
@@ -124,7 +125,7 @@ export const petsRouter = router({
|
||||
include: {
|
||||
species: { include: { translations: { where: { locale: ctx.locale } } } },
|
||||
breed: { include: { translations: { where: { locale: ctx.locale } } } },
|
||||
owner: { select: { sponsorSince: true, sponsorPeriodEnd: true } },
|
||||
owner: petCardSelect.owner,
|
||||
},
|
||||
});
|
||||
if (!pet) throw new TRPCError({ code: "NOT_FOUND" });
|
||||
|
||||
@@ -15,6 +15,7 @@ import { extractHashtags, saveHashtags } from "@/lib/hashtag-helpers";
|
||||
import { checkAgainstBlacklist } from "@/lib/blacklist";
|
||||
import { createMentionNotifications } from "@/lib/mention-helpers";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
/**
|
||||
* Posts tRPC router — photo post creation, caption edit, deletion, feed hydration.
|
||||
@@ -129,7 +130,7 @@ export const postsRouter = router({
|
||||
},
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
milestone: true,
|
||||
},
|
||||
});
|
||||
@@ -197,7 +198,7 @@ export const postsRouter = router({
|
||||
data: { caption: input.caption },
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
milestone: true,
|
||||
},
|
||||
});
|
||||
@@ -249,14 +250,14 @@ export const postsRouter = router({
|
||||
take: input.limit + 1,
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
milestone: true,
|
||||
videoPost: { select: { status: true, muxPlaybackId: true } },
|
||||
repost: {
|
||||
include: {
|
||||
originalPost: {
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
images: { orderBy: { position: "asc" } },
|
||||
milestone: true,
|
||||
},
|
||||
@@ -291,14 +292,14 @@ export const postsRouter = router({
|
||||
},
|
||||
include: {
|
||||
images: { orderBy: { position: "asc" } },
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
milestone: true,
|
||||
videoPost: { select: { status: true, muxPlaybackId: true } },
|
||||
repost: {
|
||||
include: {
|
||||
originalPost: {
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
images: { orderBy: { position: "asc" } },
|
||||
milestone: true,
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import { router, protectedProcedure } from "@/trpc/init";
|
||||
import { clerkClient } from "@clerk/nextjs/server";
|
||||
import { pickLocalizedName } from "@/lib/localized-name";
|
||||
import { getSpiderExclusionId } from "@/lib/spider-exclusion";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
|
||||
export const searchRouter = router({
|
||||
pets: protectedProcedure
|
||||
@@ -85,7 +86,7 @@ export const searchRouter = router({
|
||||
include: {
|
||||
post: {
|
||||
include: {
|
||||
pet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
pet: { select: petIdentitySelect },
|
||||
images: { orderBy: { position: "asc" }, take: 1 },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
MAX_FILE_SIZE,
|
||||
} from "@/lib/supabase-storage";
|
||||
import { randomUUID } from "crypto";
|
||||
import { petIdentitySelect } from "@/repositories/pet-repository";
|
||||
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
|
||||
import { mux } from "@/lib/mux";
|
||||
import { MAX_STORY_VIDEO_DURATION_SECS } from "@/lib/story-video-limits";
|
||||
@@ -270,7 +271,7 @@ export const storiesRouter = router({
|
||||
return ctx.prisma.storyView.findMany({
|
||||
where: { storyId: input.storyId },
|
||||
include: {
|
||||
viewerPet: { select: { id: true, name: true, nickname: true, avatarKey: true } },
|
||||
viewerPet: { select: petIdentitySelect },
|
||||
},
|
||||
orderBy: { viewedAt: "desc" },
|
||||
take: 200,
|
||||
|
||||
Reference in new issue
Block a user