fix: Move more directories

This commit is contained in:
Wanjohi
2025-09-06 16:50:44 +03:00
parent 1c1c73910b
commit 9818165a90
248 changed files with 9 additions and 9566 deletions

View File

@@ -0,0 +1,35 @@
import { timestamps } from "../drizzle/types";
import { baseGamesTable } from "../base-game/base-game.sql";
import { categoriesTable, CategoryTypeEnum } from "../categories/categories.sql";
import { foreignKey, index, pgTable, primaryKey, varchar } from "drizzle-orm/pg-core";
export const gamesTable = pgTable(
'games',
{
...timestamps,
baseGameID: varchar('base_game_id', { length: 255 })
.notNull()
.references(() => baseGamesTable.id,
{ onDelete: "cascade" }
),
categorySlug: varchar('category_slug', { length: 255 })
.notNull(),
categoryType: CategoryTypeEnum("type").notNull()
},
(table) => [
primaryKey({
columns: [table.baseGameID, table.categorySlug, table.categoryType]
}),
foreignKey({
name: "games_categories_fkey",
columns: [table.categorySlug, table.categoryType],
foreignColumns: [categoriesTable.slug, categoriesTable.type],
}).onDelete("cascade"),
index("idx_games_category_slug").on(table.categorySlug),
index("idx_games_category_type").on(table.categoryType),
index("idx_games_category_slug_type").on(
table.categorySlug,
table.categoryType
)
]
);

View File

@@ -0,0 +1,129 @@
import { z } from "zod";
import { fn } from "../utils";
import { Images } from "../images";
import { Examples } from "../examples";
import { BaseGame } from "../base-game";
import { gamesTable } from "./game.sql";
import { Categories } from "../categories";
import { eq, and, isNull } from "drizzle-orm";
import { createSelectSchema } from "drizzle-zod";
import { imagesTable } from "../images/images.sql";
import { baseGamesTable } from "../base-game/base-game.sql";
import { groupBy, map, pipe, uniqueBy, values } from "remeda";
import { categoriesTable } from "../categories/categories.sql";
import { createTransaction, useTransaction } from "../drizzle/transaction";
export namespace Game {
export const Info = z
.intersection(BaseGame.Info, Categories.Info, Images.Info)
.openapi({
ref: "Game",
description: "Detailed information about a game available in the Nestri library, including technical specifications, categories and metadata",
example: Examples.Game
})
export type Info = z.infer<typeof Info>;
export const InputInfo = createSelectSchema(gamesTable)
.omit({ timeCreated: true, timeDeleted: true, timeUpdated: true })
export const create = fn(
InputInfo,
(input) =>
createTransaction(async (tx) => {
const result =
await tx
.select()
.from(gamesTable)
.where(
and(
eq(gamesTable.categorySlug, input.categorySlug),
eq(gamesTable.categoryType, input.categoryType),
eq(gamesTable.baseGameID, input.baseGameID),
isNull(gamesTable.timeDeleted)
)
)
.limit(1)
.execute()
.then(rows => rows.at(0))
if (result) return result.baseGameID
await tx
.insert(gamesTable)
.values(input)
.onConflictDoUpdate({
target: [gamesTable.categorySlug, gamesTable.categoryType, gamesTable.baseGameID],
set: { timeDeleted: null }
})
return input.baseGameID
})
)
export const fromID = fn(
InputInfo.shape.baseGameID,
(gameID) =>
useTransaction(async (tx) =>
tx
.select({
games: baseGamesTable,
categories: categoriesTable,
images: imagesTable
})
.from(gamesTable)
.innerJoin(baseGamesTable,
eq(baseGamesTable.id, gamesTable.baseGameID)
)
.leftJoin(categoriesTable,
and(
eq(categoriesTable.slug, gamesTable.categorySlug),
eq(categoriesTable.type, gamesTable.categoryType),
)
)
.leftJoin(imagesTable,
and(
eq(imagesTable.baseGameID, gamesTable.baseGameID),
isNull(imagesTable.timeDeleted),
)
)
.where(
and(
eq(gamesTable.baseGameID, gameID),
isNull(gamesTable.timeDeleted)
)
)
.execute()
.then((rows) => serialize(rows).at(0))
)
)
export function serialize(
input: { games: typeof baseGamesTable.$inferSelect; categories: typeof categoriesTable.$inferSelect | null; images: typeof imagesTable.$inferSelect | null }[],
): z.infer<typeof Info>[] {
return pipe(
input,
groupBy((row) => row.games.id),
values(),
map((group) => {
const game = BaseGame.serialize(group[0].games)
const cats = uniqueBy(
group.map(r => r.categories).filter((c): c is typeof categoriesTable.$inferSelect => Boolean(c)),
(c) => `${c.slug}:${c.type}`
)
const imgs = uniqueBy(
group.map(r => r.images).filter((c): c is typeof imagesTable.$inferSelect => Boolean(c)),
(c) => `${c.type}:${c.imageHash}:${c.position}`
)
const byType = Categories.serialize(cats)
const byImg = Images.serialize(imgs)
return {
...game,
...byType,
...byImg
}
})
)
}
}