Skip to content

Database Schema

Synqed persists everything in PostgreSQL through Prisma 7. The full schema lives in prisma/schema.prisma.

Entity map

┌─────────────────┐     ┌──────────────────────┐
│    Schedule      │────▶│   SchedulePlayer     │
│─────────────────│     │──────────────────────│
│ id              │     │ id                   │
│ date (unique)   │     │ scheduleId (FK)      │
│ reason          │     │ userId               │
│ focus           │     │ displayName          │
│ createdAt       │     │ role (UserRole)      │
│ updatedAt       │     │ availability         │
└─────────────────┘     │ sortOrder            │
                        └──────────────────────┘

┌─────────────────┐     ┌──────────────────────┐
│  UserMapping    │     │ RecurringAvailability│
│─────────────────│     │──────────────────────│
│ discordId (PK)  │     │ id                   │
│ discordUsername │     │ userId               │
│ displayName     │     │ dayOfWeek (0–6)      │
│ role (UserRole) │     │ availability         │
│ timezone        │     │ active               │
│ isAdmin         │     │ unique(userId, day)  │
│ sortOrder       │     └──────────────────────┘
└─────────────────┘

┌─────────────────┐     ┌──────────────────────┐
│     Scrim       │────▶│    VodComment         │
│─────────────────│     │──────────────────────│
│ id              │     │ id                   │
│ date            │     │ scrimId (FK)         │
│ opponent        │     │ userName             │
│ result (enum)   │     │ timestamp            │
│ scoreUs/Them    │     │ content              │
│ map             │     └──────────────────────┘
│ matchType       │
│ ourAgents       │     ┌──────────────────────┐
│ theirAgents     │     │     Absence          │
│ vodUrl          │     │──────────────────────│
│ matchLink       │     │ id                   │
│ notes           │     │ userId               │
└─────────────────┘     │ startDate            │
                        │ endDate              │
┌─────────────────┐     │ reason               │
│    Setting      │     └──────────────────────┘
│─────────────────│
│ id              │
│ key (unique)    │
│ value           │
└─────────────────┘

Stratbook tables

┌──────────────────┐     ┌──────────────────────┐
│ StrategyFolder   │────▶│    Strategy           │
│──────────────────│     │──────────────────────│
│ id               │     │ id                   │
│ name             │     │ title                │
│ parentId (self)  │     │ map                  │
│ color            │     │ side                 │
│ sortOrder        │     │ tags                 │
└──────────────────┘     │ agents               │
                         │ content (JSON)       │
                         │ folderId (FK)        │
                         │ authorId             │
                         │ authorName           │
                         └──────┬──────┬────────┘
                                │      │
                    ┌───────────▼┐  ┌──▼───────────┐
                    │StrategyImage│  │StrategyFile  │
                    │────────────│  │──────────────│
                    │ id         │  │ id           │
                    │ strategyId │  │ strategyId   │
                    │ filename   │  │ filename     │
                    │ originalNm │  │ originalName │
                    │ mimeType   │  │ mimeType     │
                    │ size       │  │ size         │
                    └────────────┘  └──────────────┘

Tables

Schedule

ColumnTypeDescription
idint (auto)Primary key
datestring (unique)DD.MM.YYYY
reasonstring?Reason (Training, Premier, Off-Day, …)
focusstring?Detail text
createdAtdatetimeCreated
updatedAtdatetimeUpdated

SchedulePlayer

ColumnTypeDescription
idint (auto)Primary key
scheduleIdint (FK)Schedule
userIdstringDiscord ID
displayNamestringDisplay name at snapshot time
roleUserRoleMAIN / SUB / COACH
availabilitystringTime window, "x", or empty
sortOrderintDisplay order

Indexes: scheduleId, userId.

UserMapping

ColumnTypeDescription
discordIdstring (PK)Discord ID (unique)
discordUsernamestringDiscord username
displayNamestringDisplay name
roleUserRoleMAIN / SUB / COACH
timezonestring?IANA timezone (optional)
isAdminbooleanAdmin flag
sortOrderintDisplay order

Indexes: discordId, [role, sortOrder].

Scrim

ColumnTypeDescription
idstringUUID primary key
datestringDD.MM.YYYY
opponentstringOpponent name
resultScrimResultWIN / LOSS / DRAW
scoreUsintOur rounds
scoreThemintOpponent rounds
mapstringMap name
matchTypestring?Scrim, Tournament, Premier, Custom, …
ourAgentsstring?Comma-separated agents
theirAgentsstring?Comma-separated agents
vodUrlstring?VOD URL
matchLinkstring?Match link
notesstring?Notes

VodComment

ColumnTypeDescription
idint (auto)Primary key
scrimIdstring (FK)Scrim
userNamestringComment author
timestampintSeconds into the VOD
contentstringComment body

Index: [scrimId, timestamp]. Cascade: deleting a Scrim deletes its comments.

Absence

ColumnTypeDescription
idint (auto)Primary key
userIdstringDiscord ID
startDatestringFirst absent day (DD.MM.YYYY)
endDatestringLast absent day (inclusive)
reasonstring?Optional reason

Indexes: userId, [startDate, endDate].

RecurringAvailability

ColumnTypeDescription
idint (auto)Primary key
userIdstringDiscord ID
dayOfWeekint0 (Sun) – 6 (Sat)
availabilitystringTime window or "x"
activebooleanToggle

Unique: [userId, dayOfWeek].

Setting

ColumnTypeDescription
idint (auto)Primary key
keystring (unique)Dot-notation key
valuestringAlways stored as string

Notable setting keys

KeyStored asDescription
discord.channelIdsnowflakeSchedule channel ID
discord.pingRoleIdsnowflake or emptyPing role for daily/weekly posts
discord.pinnedWeekMessageIdsnowflake or emptyBot-managed pin for the weekly overview
discord.pinnedWeekStartDateDD.MM.YYYY or emptyMonday of the pinned week
scheduling.dailyPostTimeHH:MMDaily schedule post
scheduling.timezoneIANA timezoneCron timezone
scheduling.weeklyPingEnabledboolWeekly planning DM master toggle
scheduling.weeklyPingTimeHH:MMWeekly planning DM time
scheduling.weeklyPingDayscomma-separated intsCron-style weekdays (0=Sun..6=Sat)

See Configuration for the full settings catalogue.

Enums

UserRole

prisma
enum UserRole {
  MAIN
  SUB
  COACH
}

ScrimResult

prisma
enum ScrimResult {
  WIN
  LOSS
  DRAW
}

Gotchas

Date format

Dates are stored as TEXT in DD.MM.YYYY format, not as DATE. Comparisons and sorting work via string ops, so the format is non-negotiable. Use the helpers in src/shared/utils/dateFormatter.ts to produce and parse them.

Prisma client location

The generated client lives in src/generated/prisma. After any schema change run npm run db:generate.

MIT License