feat(db): add lobbies and lobby_players tables + model
This commit is contained in:
parent
a7be7152cc
commit
47a68c0315
8 changed files with 1310 additions and 10 deletions
|
|
@ -9,6 +9,7 @@ import {
|
|||
primaryKey,
|
||||
index,
|
||||
boolean,
|
||||
integer,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
import { sql, relations } from "drizzle-orm";
|
||||
|
|
@ -19,6 +20,7 @@ import {
|
|||
CEFR_LEVELS,
|
||||
SUPPORTED_DECK_TYPES,
|
||||
DIFFICULTY_LEVELS,
|
||||
LOBBY_STATUSES,
|
||||
} from "@lila/shared";
|
||||
|
||||
export const terms = pgTable(
|
||||
|
|
@ -252,12 +254,53 @@ export const accountRelations = relations(account, ({ one }) => ({
|
|||
user: one(user, { fields: [account.userId], references: [user.id] }),
|
||||
}));
|
||||
|
||||
/*
|
||||
* INTENTIONAL DESIGN DECISIONS — see decisions.md for full reasoning
|
||||
*
|
||||
* source + source_id (terms): idempotency key per import pipeline
|
||||
* display_name UNIQUE (users): multiplayer requires distinguishable names
|
||||
* UNIQUE(term_id, language_code, text): allows synonyms, prevents exact duplicates
|
||||
* updated_at omitted: misleading without a trigger to maintain it
|
||||
* FK indexes: all FK columns covered, no sequential scans on joins
|
||||
*/
|
||||
export const lobbies = pgTable(
|
||||
"lobbies",
|
||||
{
|
||||
id: uuid().primaryKey().defaultRandom(),
|
||||
code: varchar({ length: 10 }).notNull().unique(),
|
||||
hostUserId: text("host_user_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
status: varchar({ length: 20 }).notNull().default("waiting"),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
},
|
||||
(table) => [
|
||||
check(
|
||||
"lobby_status_check",
|
||||
sql`${table.status} IN (${sql.raw(LOBBY_STATUSES.map((s) => `'${s}'`).join(", "))})`,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
export const lobby_players = pgTable(
|
||||
"lobby_players",
|
||||
{
|
||||
lobbyId: uuid("lobby_id")
|
||||
.notNull()
|
||||
.references(() => lobbies.id, { onDelete: "cascade" }),
|
||||
userId: text("user_id")
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
score: integer().notNull().default(0),
|
||||
joinedAt: timestamp("joined_at", { withTimezone: true })
|
||||
.defaultNow()
|
||||
.notNull(),
|
||||
},
|
||||
(table) => [primaryKey({ columns: [table.lobbyId, table.userId] })],
|
||||
);
|
||||
|
||||
export const lobbyRelations = relations(lobbies, ({ one, many }) => ({
|
||||
host: one(user, { fields: [lobbies.hostUserId], references: [user.id] }),
|
||||
players: many(lobby_players),
|
||||
}));
|
||||
|
||||
export const lobbyPlayersRelations = relations(lobby_players, ({ one }) => ({
|
||||
lobby: one(lobbies, {
|
||||
fields: [lobby_players.lobbyId],
|
||||
references: [lobbies.id],
|
||||
}),
|
||||
user: one(user, { fields: [lobby_players.userId], references: [user.id] }),
|
||||
}));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue