2022-12-29 22:10:28 +00:00
|
|
|
import { error } from '@sveltejs/kit';
|
2023-05-15 04:08:30 +00:00
|
|
|
import { superValidate } from 'sveltekit-superforms/server';
|
2023-06-26 06:14:26 +00:00
|
|
|
import kebabCase from 'just-kebab-case';
|
2023-05-15 04:08:30 +00:00
|
|
|
import type { GameType, SearchQuery } from '$lib/types';
|
2023-08-21 05:54:04 +00:00
|
|
|
import { mapAPIGameToBoredGame } from '$lib/utils/gameMapper.js';
|
2023-05-15 04:08:30 +00:00
|
|
|
import { search_schema } from '$lib/zodValidation';
|
2023-07-30 05:00:51 +00:00
|
|
|
import type { PageServerLoad } from '../$types.js';
|
2023-09-30 09:46:05 +00:00
|
|
|
import type { BggThingDto } from 'boardgamegeekclient/dist/esm/dto/index.js';
|
2023-10-14 09:06:57 +00:00
|
|
|
import type { BggLinkDto } from 'boardgamegeekclient/dist/esm/dto/concrete/subdto/BggLinkDto.js';
|
|
|
|
|
import {
|
|
|
|
|
createArtist,
|
|
|
|
|
createCategory,
|
|
|
|
|
createDesigner,
|
|
|
|
|
createMechanic,
|
|
|
|
|
createOrUpdateGame,
|
|
|
|
|
createOrUpdateGameMinimal,
|
|
|
|
|
createPublisher
|
|
|
|
|
} from '$lib/utils/dbUtils.js';
|
2023-07-30 05:00:51 +00:00
|
|
|
// import { listGameSchema } from '$lib/config/zod-schemas.js';
|
2022-12-25 18:52:36 +00:00
|
|
|
|
2023-07-30 05:00:51 +00:00
|
|
|
/**
|
|
|
|
|
* Asynchronous function searchForGames to fetch games from a local and remote repository based on the given parameters.
|
|
|
|
|
* @async
|
|
|
|
|
* @function searchForGames
|
|
|
|
|
* @param {SearchQuery} urlQueryParams - An object that represents the search parameters. It includes properties like name, min_players,
|
|
|
|
|
* max_players, min_playtime, max_playtime, min_age, skip, limit which are used to define the search condition for games.
|
|
|
|
|
* @param {any} locals - An object that contains data related to the local server environment like user information.
|
|
|
|
|
* @param {Function} eventFetch - A function that fetches games from the local API.
|
|
|
|
|
* @returns {Object} returns an object with totalCount property which is the total number of games fetched and games property which is
|
|
|
|
|
* an array of all the games fetched. If any error occurred during the operation, it returns an object with totalCount as 0 and games as empty array.
|
|
|
|
|
* @throws will throw an error if the response received from fetching games operation is not OK (200).
|
|
|
|
|
*/
|
2023-10-14 09:06:57 +00:00
|
|
|
async function searchForGames(urlQueryParams: SearchQuery, eventFetch: Function) {
|
2022-12-25 18:52:36 +00:00
|
|
|
try {
|
2023-07-30 05:00:51 +00:00
|
|
|
console.log('urlQueryParams search games', urlQueryParams);
|
2023-10-14 09:06:57 +00:00
|
|
|
|
2023-07-30 05:00:51 +00:00
|
|
|
const headers: HeadersInit = new Headers();
|
|
|
|
|
headers.set('Content-Type', 'application/json');
|
|
|
|
|
const requestInit: RequestInit = {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
headers
|
|
|
|
|
};
|
2023-10-14 09:06:57 +00:00
|
|
|
const url = `/api/game/search${urlQueryParams ? `?${urlQueryParams}` : ''}`;
|
|
|
|
|
console.log('Calling internal api', url);
|
|
|
|
|
const response = await eventFetch(url, requestInit);
|
2023-07-30 05:00:51 +00:00
|
|
|
console.log('response from internal api', response);
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
console.log('Status not 200', response.status);
|
|
|
|
|
throw error(response.status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let games = [];
|
|
|
|
|
if (response.ok) {
|
|
|
|
|
games = await response.json();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-18 21:23:45 +00:00
|
|
|
console.log('games from DB', games);
|
2023-10-14 09:06:57 +00:00
|
|
|
|
|
|
|
|
const gameNameSearch = urlQueryParams.get('q');
|
2023-07-18 21:23:45 +00:00
|
|
|
let totalCount = games?.length || 0;
|
2022-12-25 18:52:36 +00:00
|
|
|
|
2023-10-14 09:06:57 +00:00
|
|
|
if (
|
|
|
|
|
totalCount === 0 ||
|
|
|
|
|
!games.find((game: GameType) => game.slug === kebabCase(gameNameSearch))
|
|
|
|
|
) {
|
|
|
|
|
console.log('No games found in DB for', gameNameSearch);
|
2023-09-30 09:46:05 +00:00
|
|
|
|
|
|
|
|
const externalResponse = await eventFetch(
|
|
|
|
|
`/api/external/search${urlQueryParams ? `?${urlQueryParams}` : ''}`,
|
|
|
|
|
requestInit
|
2023-06-26 06:14:26 +00:00
|
|
|
);
|
2023-09-30 09:46:05 +00:00
|
|
|
|
|
|
|
|
console.log('Back from external search', externalResponse);
|
2022-12-25 18:52:36 +00:00
|
|
|
|
2023-06-26 06:14:26 +00:00
|
|
|
if (!response.ok) {
|
|
|
|
|
console.log('Status not 200', response.status);
|
|
|
|
|
throw error(response.status);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-30 09:46:05 +00:00
|
|
|
if (externalResponse.ok) {
|
|
|
|
|
const gameResponse = await externalResponse.json();
|
|
|
|
|
console.log('response from external api', gameResponse);
|
|
|
|
|
const gameList: BggThingDto[] = gameResponse?.games;
|
|
|
|
|
totalCount = gameResponse?.totalCount;
|
2023-06-26 06:14:26 +00:00
|
|
|
console.log('totalCount', totalCount);
|
2023-10-14 09:06:57 +00:00
|
|
|
for (const game of gameList) {
|
|
|
|
|
console.log(
|
|
|
|
|
`Retrieving simplified external game details for id: ${game.id} with name ${game.name}`
|
|
|
|
|
);
|
|
|
|
|
const externalGameResponse = await eventFetch(
|
|
|
|
|
`/api/external/game/${game.id}?simplified=true`
|
|
|
|
|
);
|
|
|
|
|
if (externalGameResponse.ok) {
|
|
|
|
|
const externalGame = await externalGameResponse.json();
|
|
|
|
|
console.log('externalGame', externalGame);
|
|
|
|
|
let boredGame = mapAPIGameToBoredGame(externalGame);
|
|
|
|
|
games.push(createOrUpdateGameMinimal(boredGame));
|
2023-06-26 06:14:26 +00:00
|
|
|
}
|
2023-10-14 09:06:57 +00:00
|
|
|
}
|
2023-06-26 06:14:26 +00:00
|
|
|
}
|
2022-12-25 18:52:36 +00:00
|
|
|
}
|
2023-07-18 21:23:45 +00:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
totalCount,
|
|
|
|
|
games
|
|
|
|
|
};
|
2022-12-25 18:52:36 +00:00
|
|
|
} catch (e) {
|
|
|
|
|
console.log(`Error searching board games ${e}`);
|
2023-10-14 09:06:57 +00:00
|
|
|
// throw error(500, { message: 'Something went wrong' });
|
2022-12-25 18:52:36 +00:00
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
totalCount: 0,
|
2023-05-15 04:08:30 +00:00
|
|
|
games: []
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-14 09:06:57 +00:00
|
|
|
export const load: PageServerLoad = async ({ fetch, url }) => {
|
2023-05-15 04:08:30 +00:00
|
|
|
const defaults = {
|
|
|
|
|
limit: 10,
|
2023-07-30 05:00:51 +00:00
|
|
|
skip: 0,
|
|
|
|
|
order: 'asc',
|
|
|
|
|
sort: 'name'
|
2023-05-15 04:08:30 +00:00
|
|
|
};
|
|
|
|
|
const searchParams = Object.fromEntries(url?.searchParams);
|
2023-07-18 21:23:45 +00:00
|
|
|
console.log('searchParams', searchParams);
|
2023-05-15 04:08:30 +00:00
|
|
|
searchParams.limit = searchParams.limit || `${defaults.limit}`;
|
|
|
|
|
searchParams.skip = searchParams.skip || `${defaults.skip}`;
|
2023-09-30 09:46:05 +00:00
|
|
|
searchParams.order = searchParams.order || defaults.order;
|
|
|
|
|
searchParams.sort = searchParams.sort || defaults.sort;
|
2023-05-15 04:08:30 +00:00
|
|
|
const form = await superValidate(searchParams, search_schema);
|
2023-07-30 05:00:51 +00:00
|
|
|
// const modifyListForm = await superValidate(listGameSchema);
|
2023-05-15 04:08:30 +00:00
|
|
|
|
|
|
|
|
const queryParams: SearchQuery = {
|
|
|
|
|
limit: form.data?.limit,
|
|
|
|
|
skip: form.data?.skip,
|
2023-10-14 09:06:57 +00:00
|
|
|
q: form.data?.q
|
2023-05-15 04:08:30 +00:00
|
|
|
};
|
|
|
|
|
|
2023-06-20 18:55:21 +00:00
|
|
|
// fields: ('id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description');
|
2023-08-14 05:12:02 +00:00
|
|
|
try {
|
2023-10-16 02:42:34 +00:00
|
|
|
if (form.data?.q === '') {
|
|
|
|
|
return {
|
|
|
|
|
form,
|
|
|
|
|
searchData: {
|
|
|
|
|
totalCount: 0,
|
|
|
|
|
games: [],
|
|
|
|
|
wishlists: []
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 05:12:02 +00:00
|
|
|
if (form.data?.minAge) {
|
|
|
|
|
if (form.data?.exactMinAge) {
|
|
|
|
|
queryParams.min_age = form.data?.minAge;
|
|
|
|
|
} else {
|
|
|
|
|
queryParams.gt_min_age = form.data?.minAge === 1 ? 0 : form.data?.minAge - 1;
|
|
|
|
|
}
|
2023-05-15 04:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-14 05:12:02 +00:00
|
|
|
if (form.data?.minPlayers) {
|
|
|
|
|
if (form.data?.exactMinPlayers) {
|
|
|
|
|
queryParams.min_players = form.data?.minPlayers;
|
|
|
|
|
} else {
|
|
|
|
|
queryParams.gt_min_players = form.data?.minPlayers === 1 ? 0 : form.data?.minPlayers - 1;
|
|
|
|
|
}
|
2023-05-15 04:08:30 +00:00
|
|
|
}
|
2023-08-14 05:12:02 +00:00
|
|
|
if (form.data?.maxPlayers) {
|
|
|
|
|
if (form.data?.exactMaxPlayers) {
|
|
|
|
|
queryParams.max_players = form.data?.maxPlayers;
|
|
|
|
|
} else {
|
|
|
|
|
queryParams.lt_max_players = form.data?.maxPlayers + 1;
|
|
|
|
|
}
|
2023-05-15 04:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-14 05:12:02 +00:00
|
|
|
const newQueryParams: Record<string, string> = {};
|
|
|
|
|
for (const key in queryParams) {
|
|
|
|
|
newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`;
|
|
|
|
|
}
|
2023-05-15 04:08:30 +00:00
|
|
|
|
2023-08-14 05:12:02 +00:00
|
|
|
const urlQueryParams = new URLSearchParams(newQueryParams);
|
|
|
|
|
const searchData = await searchForGames(urlQueryParams, fetch);
|
2023-05-15 04:08:30 +00:00
|
|
|
|
2023-08-14 05:12:02 +00:00
|
|
|
return {
|
|
|
|
|
form,
|
|
|
|
|
// modifyListForm,
|
2023-10-16 02:42:34 +00:00
|
|
|
searchData,
|
|
|
|
|
wishlists: []
|
2023-08-14 05:12:02 +00:00
|
|
|
};
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(`Error searching board games ${e}`);
|
|
|
|
|
}
|
2023-05-15 04:08:30 +00:00
|
|
|
return {
|
|
|
|
|
form,
|
2023-08-14 05:12:02 +00:00
|
|
|
searchData: {
|
|
|
|
|
totalCount: 0,
|
|
|
|
|
games: []
|
|
|
|
|
},
|
|
|
|
|
wishlists: []
|
2022-12-25 18:52:36 +00:00
|
|
|
};
|
|
|
|
|
};
|
2022-11-01 00:31:36 +00:00
|
|
|
|
2023-06-02 05:22:34 +00:00
|
|
|
export const actions = {
|
2023-05-21 05:18:04 +00:00
|
|
|
random: async ({ request }): Promise<any> => {
|
|
|
|
|
const form = await superValidate(request, search_schema);
|
2022-12-25 18:52:36 +00:00
|
|
|
const queryParams: SearchQuery = {
|
|
|
|
|
order_by: 'rank',
|
|
|
|
|
ascending: false,
|
2023-01-08 19:46:22 +00:00
|
|
|
random: true,
|
|
|
|
|
fields:
|
|
|
|
|
'id,name,min_age,min_players,max_players,thumb_url,min_playtime,max_playtime,min_age,description'
|
2022-12-25 18:52:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const newQueryParams: Record<string, string> = {};
|
|
|
|
|
for (const key in queryParams) {
|
|
|
|
|
newQueryParams[key] = `${queryParams[key as keyof SearchQuery]}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const urlQueryParams = new URLSearchParams(newQueryParams);
|
|
|
|
|
|
|
|
|
|
return {
|
2023-05-21 05:18:04 +00:00
|
|
|
form,
|
|
|
|
|
searchData: await searchForGames(urlQueryParams)
|
2022-12-25 18:52:36 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|