feat: Implement Game Image Support with Metadata & Schema Updates (#277)

## Description
<!-- Briefly describe the purpose and scope of your changes -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced support for associating rich image metadata (color,
dimensions, file size) with games, organized by categories like
screenshots, box art, posters, hero art, backgrounds, logos, and icons.
- Game and library listings now include related image collections for
enhanced browsing and detail views.

- **Improvements**
- Updated game library management to use a consistent base game
identifier, improving data consistency and reliability.
- Enhanced data schemas and access permissions to allow public viewing
of game images and refined access control for game libraries.
- Added comprehensive database schema updates for games, categories,
images, and libraries to support new features and ensure data integrity.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Wanjohi
2025-05-10 22:47:28 +03:00
committed by GitHub
parent 38ad74d14a
commit 5806dc6e86
13 changed files with 2933 additions and 54 deletions

View File

@@ -0,0 +1,46 @@
import { timestamps } from "../drizzle/types";
import { baseGamesTable } from "../base-game/base-game.sql";
import { index, integer, json, pgEnum, pgTable, primaryKey, text, varchar } from "drizzle-orm/pg-core";
import { z } from "zod";
export const ImageTypeEnum = pgEnum("image_type", ["heroArt", "icon", "logo", "superHeroArt", "poster", "boxArt", "screenshot","background"])
export const ImageDimensions = z.object({
width: z.number().int(),
height: z.number().int(),
})
export const ImageColor = z.object({
hex: z.string(),
isDark: z.boolean()
})
export type ImageColor = z.infer<typeof ImageColor>;
export type ImageDimensions = z.infer<typeof ImageDimensions>;
export const imagesTable = pgTable(
"images",
{
...timestamps,
type: ImageTypeEnum("type").notNull(),
imageHash: varchar("image_hash", { length: 255 })
.notNull(),
baseGameID: varchar("base_game_id", { length: 255 })
.notNull()
.references(() => baseGamesTable.id, {
onDelete: "cascade"
}),
sourceUrl: text("source_url").notNull(),
position: integer("position").notNull().default(0),
fileSize: integer("file_size").notNull(),
dimensions: json("dimensions").$type<ImageDimensions>().notNull(),
extractedColor: json("extracted_color").$type<ImageColor>().notNull(),
},
(table) => [
primaryKey({
columns: [table.imageHash, table.type, table.baseGameID, table.position]
}),
index("idx_images_type").on(table.type),
index("idx_images_game_id").on(table.baseGameID),
]
)