mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
import { error, json } from '@sveltejs/kit';
|
|
import db from '../../../../db';
|
|
import { asc, desc, eq, ilike, or } from 'drizzle-orm';
|
|
import { games } from '$db/schema';
|
|
import kebabCase from 'just-kebab-case';
|
|
import {
|
|
FilterSchema,
|
|
PaginationSchema,
|
|
SearchSchema,
|
|
SortSchema,
|
|
} from '$lib/validations/zod-schemas';
|
|
|
|
// Search a user's collection
|
|
export const GET = async ({ url, locals }) => {
|
|
const searchParams = Object.fromEntries(url.searchParams);
|
|
|
|
const searchGames = PaginationSchema.merge(FilterSchema)
|
|
.merge(SortSchema)
|
|
.merge(SearchSchema)
|
|
.parse(searchParams);
|
|
|
|
if (searchGames.status !== 'success') {
|
|
error(400, 'Invalid request');
|
|
}
|
|
|
|
const q = searchParams?.q?.trim() || '';
|
|
const limit = parseInt(searchParams?.limit) || 10;
|
|
const skip = parseInt(searchParams?.skip) || 0;
|
|
const order: OrderDirection = searchParams?.order === 'desc' ? 'desc' : 'asc';
|
|
const exact = searchParams?.exact === 'true';
|
|
let orderBy = searchParams?.orderBy || 'slug';
|
|
|
|
if (orderBy === 'name') {
|
|
orderBy = 'slug';
|
|
}
|
|
console.log(
|
|
`q: ${q}, limit: ${limit}, skip: ${skip}, order: ${order}, exact: ${exact}, orderBy: ${orderBy}`,
|
|
);
|
|
console.log(exact);
|
|
if (exact) {
|
|
console.log('Exact Search API');
|
|
const game = await db.query.games.findFirst({
|
|
where: eq(games.name, q),
|
|
columns: {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
thumb_url: true,
|
|
},
|
|
});
|
|
|
|
if (!game) {
|
|
error(404, { message: 'No games found' });
|
|
}
|
|
const foundGames = [game];
|
|
console.log('Games found in Exact Search API', JSON.stringify(foundGames, null, 2));
|
|
return json(foundGames);
|
|
} else {
|
|
const foundGames =
|
|
(await db
|
|
.select({
|
|
id: games.id,
|
|
name: games.name,
|
|
slug: games.slug,
|
|
thumb_url: games.thumb_url,
|
|
})
|
|
.from(games)
|
|
.where(or(ilike(games.name, `%${q}%`), ilike(games.slug, `%${kebabCase(q)}%`)))
|
|
.orderBy(getOrderDirection(order)(getOrderBy(orderBy)))
|
|
.offset(skip)
|
|
.limit(limit)) || [];
|
|
// const foundGames = await db.select({
|
|
// id: games.id,
|
|
// name: games.name,
|
|
// slug: games.slug,
|
|
// thumb_url: games.thumb_url
|
|
// })
|
|
// .from(games)
|
|
// .where(sql`to_tsvector('simple', ${games.name}) || to_tsvector('simple', ${games.slug}) @@ to_tsquery('simple', ${q})`)
|
|
// .orderBy(sql`${orderBy} ${order}`).offset(skip).limit(limit) || [];
|
|
if (foundGames.length === 0) {
|
|
error(404, { message: 'No games found' });
|
|
}
|
|
console.log('Games found in Search API', JSON.stringify(foundGames, null, 2));
|
|
return json(foundGames);
|
|
}
|
|
};
|
|
|
|
type OrderDirection = 'asc' | 'desc';
|
|
|
|
const getOrderDirection = (direction: OrderDirection) => {
|
|
return direction === 'asc' ? asc : desc;
|
|
};
|
|
|
|
const getOrderBy = (orderBy: string) => {
|
|
switch (orderBy) {
|
|
case 'name':
|
|
return games.name;
|
|
case 'slug':
|
|
return games.slug;
|
|
default:
|
|
return games.slug;
|
|
}
|
|
};
|