2023-10-16 02:42:34 +00:00
|
|
|
import type { Game } from '@prisma/client';
|
|
|
|
|
import kebabCase from 'just-kebab-case';
|
|
|
|
|
import type { BggLinkDto } from 'boardgamegeekclient/dist/esm/dto/concrete/subdto';
|
2023-11-05 00:03:28 +00:00
|
|
|
import prisma from '$lib/prisma';
|
2023-10-16 02:42:34 +00:00
|
|
|
import { mapAPIGameToBoredGame } from './gameMapper';
|
2024-02-09 02:56:09 +00:00
|
|
|
import db from '$lib/drizzle';
|
|
|
|
|
import { games } from '../../schema';
|
|
|
|
|
import { eq, sql } from 'drizzle-orm';
|
2023-10-14 09:06:57 +00:00
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createArtist(locals: App.Locals, externalArtist: BggLinkDto) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbArtist = await prisma.artist.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalArtist.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (dbArtist) {
|
2023-10-17 09:28:53 +00:00
|
|
|
console.log('Artist already exists', dbArtist.name);
|
2023-10-14 09:06:57 +00:00
|
|
|
return dbArtist;
|
|
|
|
|
}
|
|
|
|
|
console.log('Creating artist', JSON.stringify(externalArtist, null, 2));
|
2023-11-05 00:03:28 +00:00
|
|
|
let artist = await prisma.artist.create({
|
2023-10-14 09:06:57 +00:00
|
|
|
data: {
|
|
|
|
|
name: externalArtist.value,
|
|
|
|
|
external_id: externalArtist.id,
|
|
|
|
|
slug: kebabCase(externalArtist.value)
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created artist', JSON.stringify(artist, null, 2));
|
|
|
|
|
return artist;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Artist');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createDesigner(locals: App.Locals, externalDesigner: BggLinkDto) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbDesigner = await prisma.designer.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalDesigner.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (dbDesigner) {
|
2023-10-17 09:28:53 +00:00
|
|
|
console.log('Designer already exists', dbDesigner.name);
|
2023-10-14 09:06:57 +00:00
|
|
|
return dbDesigner;
|
|
|
|
|
}
|
|
|
|
|
console.log('Creating designer', JSON.stringify(externalDesigner, null, 2));
|
2023-11-05 00:03:28 +00:00
|
|
|
let designer = await prisma.designer.create({
|
2023-10-14 09:06:57 +00:00
|
|
|
data: {
|
|
|
|
|
name: externalDesigner.value,
|
|
|
|
|
external_id: externalDesigner.id,
|
|
|
|
|
slug: kebabCase(externalDesigner.value)
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created designer', JSON.stringify(designer, null, 2));
|
|
|
|
|
return designer;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Designer');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createPublisher(locals: App.Locals, externalPublisher: BggLinkDto) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbPublisher = await prisma.publisher.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalPublisher.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (dbPublisher) {
|
2023-10-17 09:28:53 +00:00
|
|
|
console.log('Publisher already exists', dbPublisher.name);
|
2023-10-14 09:06:57 +00:00
|
|
|
return dbPublisher;
|
|
|
|
|
}
|
|
|
|
|
console.log('Creating publisher', JSON.stringify(externalPublisher, null, 2));
|
2023-11-05 00:03:28 +00:00
|
|
|
let publisher = await prisma.publisher.create({
|
2023-10-14 09:06:57 +00:00
|
|
|
data: {
|
|
|
|
|
name: externalPublisher.value,
|
|
|
|
|
external_id: externalPublisher.id,
|
|
|
|
|
slug: kebabCase(externalPublisher.value)
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created publisher', JSON.stringify(publisher, null, 2));
|
|
|
|
|
return publisher;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Publisher');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createCategory(locals: App.Locals, externalCategory: BggLinkDto) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbCategory = await prisma.category.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalCategory.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (dbCategory) {
|
2023-10-17 09:28:53 +00:00
|
|
|
console.log('Category already exists', dbCategory.name);
|
2023-10-14 09:06:57 +00:00
|
|
|
return dbCategory;
|
|
|
|
|
}
|
|
|
|
|
console.log('Creating category', JSON.stringify(externalCategory, null, 2));
|
2023-11-05 00:03:28 +00:00
|
|
|
let category = await prisma.category.create({
|
2023-10-14 09:06:57 +00:00
|
|
|
data: {
|
|
|
|
|
name: externalCategory.value,
|
|
|
|
|
external_id: externalCategory.id,
|
|
|
|
|
slug: kebabCase(externalCategory.value)
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created category', JSON.stringify(category, null, 2));
|
|
|
|
|
|
|
|
|
|
return category;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Category');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createMechanic(locals: App.Locals, externalMechanic: BggLinkDto) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbMechanic = await prisma.mechanic.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalMechanic.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
name: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
external_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (dbMechanic) {
|
2023-10-17 09:28:53 +00:00
|
|
|
console.log('Mechanic already exists', dbMechanic.name);
|
2023-10-14 09:06:57 +00:00
|
|
|
return dbMechanic;
|
|
|
|
|
}
|
|
|
|
|
console.log('Creating mechanic', JSON.stringify(externalMechanic, null, 2));
|
2023-11-05 00:03:28 +00:00
|
|
|
let mechanic = await prisma.mechanic.upsert({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalMechanic.id
|
|
|
|
|
},
|
|
|
|
|
create: {
|
|
|
|
|
name: externalMechanic.value,
|
|
|
|
|
external_id: externalMechanic.id,
|
|
|
|
|
slug: kebabCase(externalMechanic.value)
|
|
|
|
|
},
|
|
|
|
|
update: {
|
|
|
|
|
name: externalMechanic.value,
|
|
|
|
|
slug: kebabCase(externalMechanic.value)
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created mechanic', JSON.stringify(mechanic, null, 2));
|
|
|
|
|
|
|
|
|
|
return mechanic;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Mechanic');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-16 02:42:34 +00:00
|
|
|
export async function createExpansion(
|
2023-10-17 09:28:53 +00:00
|
|
|
locals: App.Locals,
|
2023-10-16 02:42:34 +00:00
|
|
|
game: Game,
|
|
|
|
|
externalExpansion: BggLinkDto,
|
|
|
|
|
gameIsExpansion: boolean,
|
|
|
|
|
eventFetch: Function
|
|
|
|
|
) {
|
2023-10-14 09:06:57 +00:00
|
|
|
try {
|
2023-11-05 00:03:28 +00:00
|
|
|
let dbExpansionGame = await prisma.game.findUnique({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
external_id: externalExpansion.id
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!dbExpansionGame) {
|
|
|
|
|
const externalGameResponse = await eventFetch(
|
|
|
|
|
`/api/external/game/${externalExpansion.id}?simplified=true`
|
|
|
|
|
);
|
|
|
|
|
if (externalGameResponse.ok) {
|
|
|
|
|
const externalGame = await externalGameResponse.json();
|
|
|
|
|
console.log('externalGame', externalGame);
|
|
|
|
|
let boredGame = mapAPIGameToBoredGame(externalGame);
|
2023-10-17 09:28:53 +00:00
|
|
|
dbExpansionGame = await createOrUpdateGameMinimal(locals, boredGame);
|
2023-10-14 09:06:57 +00:00
|
|
|
} else {
|
2023-10-16 02:42:34 +00:00
|
|
|
throw new Error(
|
|
|
|
|
`${gameIsExpansion ? 'Base game' : 'Expansion game'} not found and failed to create.`
|
|
|
|
|
);
|
2023-10-14 09:06:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let dbExpansion;
|
|
|
|
|
let baseGameId;
|
|
|
|
|
let gameId;
|
|
|
|
|
if (gameIsExpansion) {
|
2023-10-16 02:42:34 +00:00
|
|
|
console.log(
|
|
|
|
|
'External expansion is expansion. Looking for base game',
|
|
|
|
|
JSON.stringify(game, null, 2)
|
|
|
|
|
);
|
2023-11-05 00:03:28 +00:00
|
|
|
dbExpansion = await prisma.expansion.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
game_id: dbExpansionGame.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
base_game_id: true,
|
|
|
|
|
game_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
baseGameId = game.id;
|
|
|
|
|
gameId = dbExpansionGame.id;
|
|
|
|
|
} else {
|
2023-10-16 02:42:34 +00:00
|
|
|
console.log(
|
|
|
|
|
'External Expansion is base game. Looking for expansion',
|
|
|
|
|
JSON.stringify(game, null, 2)
|
|
|
|
|
);
|
2023-11-05 00:03:28 +00:00
|
|
|
dbExpansion = await prisma.expansion.findFirst({
|
2023-10-14 09:06:57 +00:00
|
|
|
where: {
|
|
|
|
|
base_game_id: dbExpansionGame.id
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
base_game_id: true,
|
|
|
|
|
game_id: true
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
baseGameId = dbExpansionGame.id;
|
|
|
|
|
gameId = game.id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dbExpansion) {
|
|
|
|
|
console.log('Expansion already exists', JSON.stringify(dbExpansion, null, 2));
|
|
|
|
|
return dbExpansion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log(`Creating expansion. baseGameId: ${baseGameId}, gameId: ${gameId}`);
|
2023-11-05 00:03:28 +00:00
|
|
|
let expansion = await prisma.expansion.create({
|
2023-10-14 09:06:57 +00:00
|
|
|
data: {
|
|
|
|
|
base_game_id: baseGameId,
|
|
|
|
|
game_id: gameId
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Created expansion', JSON.stringify(expansion, null, 2));
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
if (gameIsExpansion) {
|
|
|
|
|
console.log('Connecting current game to expansion');
|
2023-11-05 00:03:28 +00:00
|
|
|
await prisma.game.update({
|
2023-10-17 09:28:53 +00:00
|
|
|
where: {
|
|
|
|
|
id: gameId
|
|
|
|
|
},
|
|
|
|
|
data: {
|
|
|
|
|
expansions: {
|
|
|
|
|
connect: {
|
|
|
|
|
id: expansion.id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log('Connecting current game to base game');
|
2023-11-05 00:03:28 +00:00
|
|
|
await prisma.game.update({
|
2023-10-17 09:28:53 +00:00
|
|
|
where: {
|
2023-11-05 00:03:28 +00:00
|
|
|
id: baseGameId
|
2023-10-17 09:28:53 +00:00
|
|
|
},
|
|
|
|
|
data: {
|
|
|
|
|
expansions: {
|
|
|
|
|
connect: {
|
|
|
|
|
id: expansion.id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-14 09:06:57 +00:00
|
|
|
return expansion;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
|
|
|
|
throw new Error('Something went wrong creating Expansion');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createOrUpdateGameMinimal(locals: App.Locals, game: Game) {
|
2023-10-14 09:06:57 +00:00
|
|
|
console.log('Creating or updating minimal game data', JSON.stringify(game, null, 2));
|
|
|
|
|
const externalUrl = `https://boardgamegeek.com/boardgame/${game.external_id}`;
|
2024-02-09 02:56:09 +00:00
|
|
|
await db.insert(games).values({
|
|
|
|
|
external_id: game.external_id,
|
|
|
|
|
name: game.name,
|
|
|
|
|
slug: kebabCase(game.name),
|
|
|
|
|
description: game.description,
|
|
|
|
|
url: externalUrl,
|
|
|
|
|
thumb_url: game.thumb_url,
|
|
|
|
|
image_url: game.image_url,
|
|
|
|
|
min_age: game.min_age || 0,
|
|
|
|
|
min_players: game.min_players || 0,
|
|
|
|
|
max_players: game.max_players || 0,
|
|
|
|
|
min_playtime: game.min_playtime || 0,
|
|
|
|
|
max_playtime: game.max_playtime || 0,
|
|
|
|
|
year_published: game.year_published || 0,
|
|
|
|
|
}).onDuplicateKeyUpdate({ set: { external_id: sql`external_id` } });
|
|
|
|
|
|
|
|
|
|
return db.query.games.findFirst({ where: eq(games.external_id, game.external_id) });
|
2023-10-14 09:06:57 +00:00
|
|
|
}
|
|
|
|
|
|
2023-10-17 09:28:53 +00:00
|
|
|
export async function createOrUpdateGame(locals: App.Locals, game: Game) {
|
2023-10-14 09:06:57 +00:00
|
|
|
console.log('Creating or updating game', JSON.stringify(game, null, 2));
|
|
|
|
|
const categoryIds = game.categories;
|
|
|
|
|
const mechanicIds = game.mechanics;
|
|
|
|
|
const publisherIds = game.publishers;
|
|
|
|
|
const designerIds = game.designers;
|
|
|
|
|
const artistIds = game.artists;
|
2023-10-17 09:28:53 +00:00
|
|
|
// const expansionIds = game.expansions;
|
2023-10-14 09:06:57 +00:00
|
|
|
const externalUrl = `https://boardgamegeek.com/boardgame/${game.external_id}`;
|
|
|
|
|
console.log('categoryIds', categoryIds);
|
|
|
|
|
console.log('mechanicIds', mechanicIds);
|
2024-02-09 02:56:09 +00:00
|
|
|
await db.transaction(async (transaction) => {
|
|
|
|
|
const
|
|
|
|
|
});
|
|
|
|
|
await db.insert(games).values({
|
2023-10-14 09:06:57 +00:00
|
|
|
include: {
|
|
|
|
|
mechanics: true,
|
|
|
|
|
publishers: true,
|
|
|
|
|
designers: true,
|
|
|
|
|
artists: true,
|
|
|
|
|
expansions: true
|
|
|
|
|
},
|
|
|
|
|
where: {
|
|
|
|
|
external_id: game.external_id
|
|
|
|
|
},
|
|
|
|
|
create: {
|
|
|
|
|
name: game.name,
|
|
|
|
|
slug: kebabCase(game.name),
|
|
|
|
|
description: game.description,
|
|
|
|
|
external_id: game.external_id,
|
|
|
|
|
url: externalUrl,
|
|
|
|
|
thumb_url: game.thumb_url,
|
|
|
|
|
image_url: game.image_url,
|
|
|
|
|
min_age: game.min_age || 0,
|
|
|
|
|
min_players: game.min_players || 0,
|
|
|
|
|
max_players: game.max_players || 0,
|
|
|
|
|
min_playtime: game.min_playtime || 0,
|
|
|
|
|
max_playtime: game.max_playtime || 0,
|
|
|
|
|
year_published: game.year_published || 0,
|
|
|
|
|
last_sync_at: new Date(),
|
|
|
|
|
categories: {
|
|
|
|
|
connect: categoryIds
|
|
|
|
|
},
|
|
|
|
|
mechanics: {
|
|
|
|
|
connect: mechanicIds
|
|
|
|
|
},
|
|
|
|
|
publishers: {
|
|
|
|
|
connect: publisherIds
|
|
|
|
|
},
|
|
|
|
|
designers: {
|
|
|
|
|
connect: designerIds
|
|
|
|
|
},
|
|
|
|
|
artists: {
|
|
|
|
|
connect: artistIds
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
update: {
|
|
|
|
|
name: game.name,
|
|
|
|
|
slug: kebabCase(game.name),
|
|
|
|
|
description: game.description,
|
|
|
|
|
external_id: game.external_id,
|
|
|
|
|
url: externalUrl,
|
|
|
|
|
thumb_url: game.thumb_url,
|
|
|
|
|
image_url: game.image_url,
|
|
|
|
|
min_age: game.min_age || 0,
|
|
|
|
|
min_players: game.min_players || 0,
|
|
|
|
|
max_players: game.max_players || 0,
|
|
|
|
|
min_playtime: game.min_playtime || 0,
|
|
|
|
|
max_playtime: game.max_playtime || 0,
|
|
|
|
|
year_published: game.year_published || 0,
|
|
|
|
|
last_sync_at: new Date(),
|
|
|
|
|
categories: {
|
|
|
|
|
connect: categoryIds
|
|
|
|
|
},
|
|
|
|
|
mechanics: {
|
|
|
|
|
connect: mechanicIds
|
|
|
|
|
},
|
|
|
|
|
publishers: {
|
|
|
|
|
connect: publisherIds
|
|
|
|
|
},
|
|
|
|
|
designers: {
|
|
|
|
|
connect: designerIds
|
|
|
|
|
},
|
|
|
|
|
artists: {
|
|
|
|
|
connect: artistIds
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|