mirror of
https://github.com/trafficlunar/tomodachi-share.git
synced 2026-06-28 14:44:15 +00:00
refactor: remove /api/mii/list
what is the point of next.js if i'm not even using it properly (should also hopefully improve SEO)
This commit is contained in:
parent
c4a8e82313
commit
5a01bfb234
5 changed files with 215 additions and 245 deletions
|
|
@ -1,116 +0,0 @@
|
|||
import { NextRequest } from "next/server";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { z } from "zod";
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { querySchema } from "@/lib/schemas";
|
||||
import { RateLimit } from "@/lib/rate-limit";
|
||||
|
||||
const searchSchema = z.object({
|
||||
q: querySchema.optional(),
|
||||
sort: z.enum(["newest", "likes"], { message: "Sort must be either 'newest' or 'likes'" }).default("newest"),
|
||||
tags: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) =>
|
||||
value
|
||||
?.split(",")
|
||||
.map((tag) => tag.trim())
|
||||
.filter((tag) => tag.length > 0)
|
||||
),
|
||||
// todo: incorporate tagsSchema
|
||||
// Profiles
|
||||
userId: z.coerce
|
||||
.number({ message: "User ID must be a number" })
|
||||
.int({ message: "User ID must be an integer" })
|
||||
.positive({ message: "User ID must be valid" })
|
||||
.optional(),
|
||||
// Pages
|
||||
limit: z.coerce
|
||||
.number({ message: "Limit must be a number" })
|
||||
.int({ message: "Limit must be an integer" })
|
||||
.min(1, { message: "Limit must be at least 1" })
|
||||
.max(100, { message: "Limit cannot be more than 100" })
|
||||
.optional(),
|
||||
page: z.coerce
|
||||
.number({ message: "Page must be a number" })
|
||||
.int({ message: "Page must be an integer" })
|
||||
.min(1, { message: "Page must be at least 1" })
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const session = await auth();
|
||||
|
||||
const rateLimit = new RateLimit(request, 30);
|
||||
const check = await rateLimit.handle();
|
||||
if (check) return check;
|
||||
|
||||
const parsed = searchSchema.safeParse(Object.fromEntries(request.nextUrl.searchParams));
|
||||
if (!parsed.success) return rateLimit.sendResponse({ error: parsed.error.errors[0].message }, 400);
|
||||
|
||||
const { q: query, sort, tags, userId, page = 1, limit = 24 } = parsed.data;
|
||||
|
||||
const where: Prisma.MiiWhereInput = {
|
||||
// Searching
|
||||
...(query && {
|
||||
OR: [{ name: { contains: query, mode: "insensitive" } }, { tags: { has: query } }],
|
||||
}),
|
||||
// Tag filtering
|
||||
...(tags && tags.length > 0 && { tags: { hasEvery: tags } }),
|
||||
// Profiles
|
||||
...(userId && { userId }),
|
||||
};
|
||||
|
||||
// Sorting by likes or newest
|
||||
const orderBy: Prisma.MiiOrderByWithRelationInput[] =
|
||||
sort === "likes" ? [{ likedBy: { _count: "desc" } }, { name: "asc" }] : [{ createdAt: "desc" }, { name: "asc" }];
|
||||
|
||||
const select: Prisma.MiiSelect = {
|
||||
id: true,
|
||||
// Don't show when userId is specified
|
||||
...(!userId && {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
name: true,
|
||||
imageCount: true,
|
||||
tags: true,
|
||||
createdAt: true,
|
||||
// Mii liked check
|
||||
...(session?.user?.id && {
|
||||
likedBy: {
|
||||
where: { userId: Number(session.user.id) },
|
||||
select: { userId: true },
|
||||
},
|
||||
}),
|
||||
// Like count
|
||||
_count: {
|
||||
select: { likedBy: true },
|
||||
},
|
||||
};
|
||||
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [totalCount, filteredCount, list] = await Promise.all([
|
||||
prisma.mii.count({ where: { ...where, userId } }),
|
||||
prisma.mii.count({ where, skip, take: limit }),
|
||||
prisma.mii.findMany({ where, orderBy, select, skip: (page - 1) * limit, take: limit }),
|
||||
]);
|
||||
|
||||
return rateLimit.sendResponse({
|
||||
total: totalCount,
|
||||
filtered: filteredCount,
|
||||
lastPage: Math.ceil(totalCount / limit),
|
||||
miis: list.map(({ _count, likedBy, ...rest }) => ({
|
||||
...rest,
|
||||
likes: _count.likedBy,
|
||||
isLiked: session?.user?.id ? likedBy.length > 0 : false,
|
||||
})),
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue