feat(backend): add fastify api, auth, prisma schema and jobs
This commit is contained in:
58
apps/backend/src/modules/public/public.routes.ts
Normal file
58
apps/backend/src/modules/public/public.routes.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { markSeenSchema } from '@family-wishlist/shared';
|
||||
import { NotFoundError } from '../../utils/errors.js';
|
||||
|
||||
export default async function publicRoutes(app: FastifyInstance) {
|
||||
app.get('/:slug', async (request) => {
|
||||
const { slug } = request.params as { slug: string };
|
||||
const user = await app.prisma.user.findUnique({
|
||||
where: { slug },
|
||||
select: { slug: true, displayName: true, bio: true, avatarUrl: true },
|
||||
});
|
||||
if (!user) throw new NotFoundError('Profile');
|
||||
return user;
|
||||
});
|
||||
|
||||
app.get('/:slug/wishes', async (request) => {
|
||||
const { slug } = request.params as { slug: string };
|
||||
const user = await app.prisma.user.findUnique({ where: { slug }, select: { id: true } });
|
||||
if (!user) throw new NotFoundError('Profile');
|
||||
|
||||
const wishes = await app.prisma.wish.findMany({
|
||||
where: { userId: user.id, status: { in: ['ACTIVE', 'COMPLETED'] } },
|
||||
orderBy: [{ status: 'asc' }, { createdAt: 'desc' }],
|
||||
});
|
||||
|
||||
const wishIds = wishes.map((w) => w.id);
|
||||
const seen = wishIds.length
|
||||
? await app.prisma.guestView.findMany({
|
||||
where: { guestId: request.guestId, wishId: { in: wishIds } },
|
||||
select: { wishId: true },
|
||||
})
|
||||
: [];
|
||||
const seenSet = new Set(seen.map((s) => s.wishId));
|
||||
return wishes.map((w) => ({
|
||||
...w,
|
||||
isNewForGuest: w.status === 'ACTIVE' && !seenSet.has(w.id),
|
||||
}));
|
||||
});
|
||||
|
||||
app.post('/:slug/views', async (request) => {
|
||||
const { slug } = request.params as { slug: string };
|
||||
const body = markSeenSchema.parse(request.body);
|
||||
|
||||
const user = await app.prisma.user.findUnique({ where: { slug }, select: { id: true } });
|
||||
if (!user) throw new NotFoundError('Profile');
|
||||
|
||||
// Filter wishIds to those that actually belong to this user (avoid cross-user pollution).
|
||||
const owned = await app.prisma.wish.findMany({
|
||||
where: { userId: user.id, id: { in: body.wishIds } },
|
||||
select: { id: true },
|
||||
});
|
||||
if (owned.length === 0) return { marked: 0 };
|
||||
|
||||
const data = owned.map((w) => ({ guestId: request.guestId, wishId: w.id }));
|
||||
const res = await app.prisma.guestView.createMany({ data, skipDuplicates: true });
|
||||
return { marked: res.count };
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user