Database Reference
The API persists data in MySQL through Drizzle ORM (libs/api/db).
For setup and migration commands, see the How-To section below.
NestJS Integration
DbModule is global (@Global()). It registers DrizzleMySqlModule with the tag 'DB_PROD'.
Services that need the database inject it with @Inject('DB_PROD').
Schema Tables
Source of truth: libs/api/db/src/lib/schema.ts
user
Stores player accounts.
| Column | Type | Notes |
|---|---|---|
id | varchar(36) | Primary key |
name | text | Display name |
email | varchar(255) | Unique |
nickname | varchar(255) | Unique, required on sign-up |
emailVerified | boolean | Must be true for profile changes |
image | text | Nullable |
createdAt, updatedAt | timestamp | Auto-managed |
session
Stores active sessions. The API deletes all rows for a user after a password change.
| Column | Type | Notes |
|---|---|---|
id | varchar(36) | Primary key |
token | varchar(255) | Unique session token |
userId | varchar(36) | FK → user.id |
expiresAt | timestamp | Expiry managed by Better Auth |
account
Stores auth provider records. For email/password auth, password holds the bcrypt hash.
| Column | Type | Notes |
|---|---|---|
id | varchar(36) | Primary key |
accountId | text | Provider-specific account ID |
providerId | text | 'credential' for email/password |
userId | varchar(36) | FK → user.id |
password | text | Nullable — only set for credential accounts |
accessToken, refreshToken, idToken | text | Nullable — OAuth-managed by Better Auth |
accessTokenExpiresAt, refreshTokenExpiresAt | timestamp | Nullable — OAuth token expiry |
scope | text | Nullable — OAuth scope |
createdAt, updatedAt | timestamp | Auto-managed |
verification
Better Auth uses this table internally for email verification tokens.
pending_account_change
Stores in-progress profile/email/password confirmation workflows.
| Column | Type | Notes |
|---|---|---|
type | varchar(32) | 'profile', 'email', or 'password' |
stage | varchar(64) | 'pending', 'confirm-old-email', 'verify-new-email' |
tokenHash | varchar(64) | SHA-256 of the token sent in the email. Unique. |
callbackUrl | text | Frontend URL that receives the ?token= param |
newName | text | Nullable — set for profile changes |
newNickname | varchar(255) | Nullable — set for profile changes |
newEmail | varchar(255) | Nullable — set for email changes |
newPasswordHash | text | Nullable — set for password changes |
expiresAt | timestamp | TTL: 24 hours from creation |
Environment Variables
getMysqlConnectionOptions() reads .env from the Nx workspace root.
| Variable | Required | Default | Notes |
|---|---|---|---|
MYSQL_USER | ✅ | — | |
MYSQL_PASSWORD | ✅ | — | |
MYSQL_DB | ✅ | — | |
MYSQL_HOST | ❌ | localhost:3306 | Format: host:port |
How To Manage the Schema
All commands run through Nx:
# Create a new migration from schema changes
pnpm nx run db:generate
# Apply pending migrations
pnpm nx run db:migrate
# Verify no schema drift exists
pnpm nx run db:check
# Open Drizzle Studio (visual DB editor)
pnpm nx run db:studio
To add a table: Update schema.ts, then run generate and migrate.
To modify a table: Edit schema.ts, then run generate and migrate.