From 89cb385e335eb773ac5b3e5a441ce9a90cca1632 Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Sat, 25 Apr 2026 11:39:20 +0800 Subject: [PATCH] feat(db): add core Drizzle schema tables (hardware, games, gameVersions) - Create lib/db/schema/ directory with barrel export index.ts - Add hardware table with device_type enum (handled/console) - Add games table with Steam metadata, sync fields, and JSON genres - Add game_versions table with composite unique (gameId, buildId) and cascade delete Refs: Chunk 2 of database schema implementation --- lib/db/schema/gameVersions.ts | 25 +++++++++++++++++++++++++ lib/db/schema/games.ts | 27 +++++++++++++++++++++++++++ lib/db/schema/hardware.ts | 10 ++++++++++ lib/db/schema/index.ts | 6 ++++++ 4 files changed, 68 insertions(+) create mode 100644 lib/db/schema/gameVersions.ts create mode 100644 lib/db/schema/games.ts create mode 100644 lib/db/schema/hardware.ts create mode 100644 lib/db/schema/index.ts diff --git a/lib/db/schema/gameVersions.ts b/lib/db/schema/gameVersions.ts new file mode 100644 index 0000000..5db9a05 --- /dev/null +++ b/lib/db/schema/gameVersions.ts @@ -0,0 +1,25 @@ +import { + boolean, + pgTable, + text, + timestamp, + unique, +} from "drizzle-orm/pg-core" +import { games } from "./games" + +export const gameVersions = pgTable( + "game_versions", + { + id: text("id") + .primaryKey() + .$defaultFn(() => crypto.randomUUID()), + gameId: text("game_id") + .notNull() + .references(() => games.id, { onDelete: "cascade" }), + buildId: text("build_id"), + versionString: text("version_string"), + isLatest: boolean("is_latest").default(false).notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), + }, + (table) => [unique("game_build_unique").on(table.gameId, table.buildId)] +) diff --git a/lib/db/schema/games.ts b/lib/db/schema/games.ts new file mode 100644 index 0000000..656f691 --- /dev/null +++ b/lib/db/schema/games.ts @@ -0,0 +1,27 @@ +import { + boolean, + integer, + jsonb, + pgTable, + text, + timestamp, +} from "drizzle-orm/pg-core" + +export const games = pgTable("games", { + id: text("id") + .primaryKey() + .$defaultFn(() => crypto.randomUUID()), + steamAppId: integer("steam_app_id").unique().notNull(), + title: text("title").notNull(), + description: text("description"), + publisher: text("publisher"), + developer: text("developer"), + genres: jsonb("genres").$type(), + headerImage: text("header_image"), + capsuleImage: text("capsule_image"), + storeUrl: text("store_url"), + lastSync: timestamp("last_sync"), + syncStatus: text("sync_status").default("pending"), + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at").defaultNow().notNull(), +}) diff --git a/lib/db/schema/hardware.ts b/lib/db/schema/hardware.ts new file mode 100644 index 0000000..50ea668 --- /dev/null +++ b/lib/db/schema/hardware.ts @@ -0,0 +1,10 @@ +import { pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core" + +export const deviceTypeEnum = pgEnum("device_type", ["handled", "console"]) + +export const hardware = pgTable("hardware", { + slug: text("slug").primaryKey(), + name: text("name").notNull(), + deviceType: deviceTypeEnum("device_type").notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), +}) diff --git a/lib/db/schema/index.ts b/lib/db/schema/index.ts new file mode 100644 index 0000000..2d99c03 --- /dev/null +++ b/lib/db/schema/index.ts @@ -0,0 +1,6 @@ +// Barrel export — will be populated as schema files are created +export * from "./games" +export * from "./gameVersions" +export * from "./hardware" +export * from "./performanceEntries" +export * from "./gamePlatformSupport"