From 36bc43105b7db209b79b0eade4c2142d165fbdae Mon Sep 17 00:00:00 2001 From: clxxiii Date: Fri, 31 May 2024 22:23:23 -0400 Subject: [PATCH 01/11] update schema with new 'block' system --- prisma/schema.prisma | 415 ++++++++++++++----------------------------- 1 file changed, 130 insertions(+), 285 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e2cfae7..de239db 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,30 +15,6 @@ datasource db { url = env("DATABASE_URL") } -model Global { - id Int @id @default(autoincrement()) - ties Int @default(0) -} - -model OsuBadge { - id Int @id @default(autoincrement()) - awarded_at DateTime - description String - image_url String - url String - users User[] -} - -model UserTitle { - id Int @id @default(autoincrement()) - awarded_at DateTime - name String - description String - image_url String - url String - users User[] -} - model User { id Int @id username String @@ -54,41 +30,11 @@ model User { hit_accuracy Float pp Float - osu_token OsuOauth? - discord_accounts DiscordAccount[] - twitch_accounts TwitchAccount[] - in_teams UserInTeam[] - osu_badges OsuBadge[] - titles UserTitle[] - host_of Tournament[] - sessions UserSession[] - invites TeamInvite[] - scores Score[] -} - -model DiscordAccount { - user User @relation(fields: [osu_id], references: [id]) - osu_id Int - id String @id - avatar String - discriminator String - flags Int - username String - - token DiscordOauth? -} - -model TwitchAccount { - user User @relation(fields: [osu_id], references: [id]) - osu_id Int - id Int @id - username String - requests_enabled Boolean @default(false) - req_require_live Boolean @default(false) - req_require_category Boolean @default(false) - tournaments Tournament[] - - token TwitchOauth? + osu_token OsuOauth? + in_teams UserInTeam[] + host_of Tournament[] + invites TeamInvite[] + scores Score[] } model OsuOauth { @@ -102,51 +48,6 @@ model OsuOauth { user User @relation(fields: [user_id], references: [id]) } -model DiscordOauth { - user_id String @id - last_update DateTime @default(now()) - access_token String - expires_in Int - refresh_token String - token_type String - scope String - - user DiscordAccount @relation(fields: [user_id], references: [id]) -} - -model TwitchOauth { - user_id Int @id - last_update DateTime @default(now()) - access_token String - expires_at BigInt - refresh_token String - token_type String - - user TwitchAccount @relation(fields: [user_id], references: [id]) -} - -model UserSession { - id String @id - user User @relation(fields: [osu_id], references: [id]) - osu_id Int - created_at DateTime @default(now()) - last_used DateTime @default(now()) - device String? - browser String? - os String? -} - -model Guild { - guild_id String @id - change_nickname Boolean - linked_role String? - player_role String? - match_results_channel String? - manager_admin_disabled Boolean @default(false) - tournaments Tournament[] - active_tournament Int? -} - model Tournament { id Int @id @default(autoincrement()) acronym String @@ -157,16 +58,13 @@ model Tournament { icon_url String allow_registrations Boolean rounds Round[] - guild Guild? @relation(fields: [guild_id], references: [guild_id]) guild_id String? private Boolean @default(false) teams Team[] - twitch_account_id Int? - twitch_channel TwitchAccount? @relation(fields: [twitch_account_id], references: [id]) - mod_multipliers ModMultiplier[] - hosts User[] - settings TournamentSettings? + hosts User[] + settings TournamentSettings? + ModMultiplier ModMultiplier[] } // A model that holds the tournament's settings required to run a match. @@ -175,66 +73,59 @@ model Tournament { model TournamentSettings { id Int @id @default(autoincrement()) - force_nf Boolean - score_mode Int - team_mode Int - team_size Int - x_v_x_mode Int - fm_mods Int @default(1) // How many mods are required for freemod picks - double_pick Int @default(1) // 0: No double picking; 1: Only double picking NM; 2 Double picking allowed - double_ban Int @default(1) // 0: No double banning; 1: Only double banning NM; 2 Double banning allowed + force_nf Boolean + score_mode Int + team_mode Int + team_size Int + x_v_x_mode Int + fm_mods Int @default(1) // How many mods are required for freemod picks + double_pick Int @default(1) // 0: No double picking; 1: Only double picking NM; 2 Double picking allowed + double_ban Int @default(1) // 0: No double banning; 1: Only double banning NM; 2 Double banning allowed + mod_multipliers ModMultiplier[] for_tournament Tournament? @relation(fields: [tournament_id], references: [id]) tournament_id Int? @unique for_match Match? @relation(fields: [match_id], references: [id]) match_id Int? @unique + MapInPool MapInPool[] } model ModMultiplier { - id Int @id @default(autoincrement()) - tournament Tournament @relation(fields: [tournament_id], references: [id]) + id Int @id @default(autoincrement()) + tournament Tournament @relation(fields: [tournament_id], references: [id]) tournament_id Int mod_string String - match_exactly Boolean @default(false) + match_exactly Boolean @default(false) multiplier Float + settings_for TournamentSettings[] } model Round { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) acronym String name String - is_qualifier Boolean @default(false) matches Match[] - tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) + tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) tournament_id Int - mappools Mappool[] - settings RoundSettings? + mappools MappoolInRound[] } -// A model that holds the rounds's settings required to run a match. -// These settings exist inside it's own model so that a match can -// be run without instantiating a full tournament object. -model RoundSettings { - id Int @id @default(autoincrement()) - - bans Int - best_of Int - protects Int +model MappoolInRound { + mappool Mappool @relation(fields: [mappool_id], references: [id]) + round Round @relation(fields: [round_id], references: [id]) + mappool_id Int + round_id Int - for_round Round? @relation(fields: [round_id], references: [id]) - round_id Int? @unique - for_match Match? @relation(fields: [match_id], references: [id]) - match_id Int? @unique + @@id([mappool_id, round_id]) } model Mappool { id Int @id @default(autoincrement()) name String - description String? map_in_pools MapInPool[] public Boolean @default(false) - rounds Round[] + in_rounds MappoolInRound[] in_matches MappoolInMatch[] } @@ -248,15 +139,16 @@ model TeamInvite { } model MapInPool { - identifier String // NM1, NM2 etc. - mods String - data Map? @relation(fields: [map_id], references: [id]) - map_id Int? - mod_priority Int @default(0) - map_order Int? - mappool Mappool @relation(fields: [mappool_id], references: [id], onDelete: Cascade) - mappool_id Int - in_matches MapInMatch[] + identifier String // NM1, NM2 etc. + mods String + data Map? @relation(fields: [map_id], references: [id]) + map_id Int? + map_order Int? + mappool Mappool @relation(fields: [mappool_id], references: [id], onDelete: Cascade) + mappool_id Int + used_in MatchBlock[] + settings TournamentSettings? @relation(fields: [tournamentSettingsId], references: [id]) + tournamentSettingsId Int? @@id([identifier, mappool_id]) } @@ -265,59 +157,37 @@ model MapInPool { // osu!standard only model Map { // Beatmap attributes - id Int @id - beatmapset_id Int - star_rating Float //'difficulty_rating' - status String - total_length Int - diff_mapper_user_id Int //'user_id' - difficulty_name String //'version' - max_combo Int - - // BeatmapDifficultyAttributes attributes - aim_difficulty Float - approach_rate Float - flashlight_difficulty Float - overall_difficulty Float - slider_factor Float - speed_difficulty Float - - // Mod star rating (only fetched and filled in when needed) + id Int @id + beatmapset_id Int + + title String + artist String + difficulty_name String //'version' + + // Web display properties + url String + cover_url String //'cover.slimcover@2x' + status String + total_length Int + max_combo Int + bpm Float + last_updated DateTime + + cs Float + ar Float + od Float + hp Float + + star_rating Float //'difficulty_rating' + // Fetched when needed star_rating_dt Float? star_rating_hr Float? star_rating_ez Float? star_rating_ht Float? - // BeatmapExtended attributes - bpm Float - count_circles Int - count_sliders Int - count_spinners Int - circle_size Float //'cs', changed it to be consistent with the other attributes - hp_drain Float //'drain' - hit_length Int //same as drain time (I think??) - last_updated DateTime - url String - - // Beatmapset attributes - artist String - artist_unicode String - cover_url String //Cover art: 'cover.cover' - cover_2x_url String //'cover.cover@2x' - card_url String //'cover.card' - card_2x_url String //'cover.card@2x' - list_url String //'cover.list' - list_2x_url String //'cover.list@2x' - slim_cover_url String //'cover.slimcover' - slim_cover_2x_url String //'cover.slimcover@2x' - preview_url String //the song preview - title String - title_unicode String - set_mapper_user_id Int //'user_id' - - // BeatmapsetExtended attributes + // Whether a user is able to download using + // osu!direct/official servers available Boolean - // ^ true if 'availability.download_disabled' is false and 'deleted_at' is null // Other fetch_time DateTime @default(now()) @@ -325,19 +195,17 @@ model Map { } model Team { - id Int @id @default(autoincrement()) - name String - icon_url String - color String - members UserInTeam[] - tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) - tournament_id Int - scrim Boolean @default(false) - timezone Int? // UTC Offset - in_matches TeamInMatch[] - in_qualifier_matches TeamInQualifierMatch[] - invited_users TeamInvite[] - scores TeamScore[] + id Int @id @default(autoincrement()) + name String + icon_url String + color String + members UserInTeam[] + tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) + tournament_id Int + timezone Int? // UTC Offset + in_matches TeamInMatch[] + invited_users TeamInvite[] + scores TeamScore[] } model UserInTeam { @@ -351,73 +219,69 @@ model UserInTeam { } model Match { - id Int @id @default(autoincrement()) - teams TeamInMatch[] - start_time DateTime? - message_id String? - channel_id String? - mp_link String? - waiting_on Int? // Index of team in teams array - round Round? @relation(fields: [round_id], references: [id]) - round_id Int? - map_history MapInMatch[] - state Int + id Int @id @default(autoincrement()) + teams TeamInMatch[] + start_time DateTime? + mp_link String? + round Round? @relation(fields: [round_id], references: [id]) + round_id Int? + + waiting_on Int? // ID of the team in match, who's turn is it + sections BlockSection[] + current_section Int // ID of current block section + block_in_section Int // ID of block scrim Boolean @default(false) tournament_settings TournamentSettings? - round_settings RoundSettings? mappools MappoolInMatch[] } -model TeamInMatch { - match_id Int - team_id Int - match Match @relation(fields: [match_id], references: [id], onDelete: Cascade) - team Team @relation(fields: [team_id], references: [id], onDelete: Cascade) - score Int - roll Int? - pick_order Int? - ban_order Int? - aborts Int @default(0) - faults Int @default(0) - warmed_up Boolean @default(false) - bans MapInMatch[] @relation("banned") - wins MapInMatch[] @relation("won") - picks MapInMatch[] @relation("picked") - protects MapInMatch[] @relation("protected") - winner Boolean? - - @@id([team_id, match_id]) +model BlockSection { + id Int @id @default(autoincrement()) + + match Match @relation(fields: [match_id], references: [id]) + match_id Int + + action String + blocks MatchBlock[] + + @@unique([id, action]) } -model MapInMatch { - map MapInPool @relation(fields: [map_identifier, pool_id], references: [identifier, mappool_id], onDelete: Cascade) - match Match @relation(fields: [match_id], references: [id], onDelete: Cascade) - match_id Int - map_identifier String - pool_id Int +model MatchBlock { + id Int @id @default(autoincrement()) - scores Score[] - team_scores TeamScore[] + section BlockSection @relation(fields: [section_id, action], references: [id, action]) + section_id Int + action String + + // Link a map + map MapInPool? @relation(fields: [map_identifier, pool_id], references: [identifier, mappool_id]) + map_identifier String? + pool_id Int? - protected_by TeamInMatch? @relation(fields: [match_id, protected_by_id], references: [match_id, team_id], name: "protected") - protected_by_id Int? + acted_on_by TeamInMatch? @relation(fields: [acted_on_by_id], references: [id]) + acted_on_by_id Int - banned_by TeamInMatch? @relation(fields: [match_id, banned_by_id], references: [match_id, team_id], name: "banned") - banned_by_id Int? + scores Score[] + team_scores TeamScore[] +} - picked_by TeamInMatch? @relation(fields: [match_id, picked_by_id], references: [match_id, team_id], name: "picked") - picked_by_id Int? - pick_number Int? - pick_team_number Int? +model TeamInMatch { + id Int @id @default(autoincrement()) - won_by TeamInMatch? @relation(fields: [match_id, won_by_id], references: [match_id, team_id], name: "won") - won_by_id Int? + match_id Int + team_id Int? + match Match @relation(fields: [match_id], references: [id], onDelete: Cascade) + team Team? @relation(fields: [team_id], references: [id]) + score Int + roll Int? + aborts Int @default(0) + faults Int @default(0) - qualifier QualifierMatch? @relation(fields: [qualifier_id], references: [id]) - qualifier_id Int? + actions MatchBlock[] - @@id([map_identifier, match_id]) + winner Boolean? } model Score { @@ -426,9 +290,8 @@ model Score { score Float mods String @default("") - map MapInMatch @relation(fields: [map_identifier, match_id], references: [map_identifier, match_id]) - map_identifier String - match_id Int + block MatchBlock @relation(fields: [block_id], references: [id]) + block_id Int user User @relation(fields: [user_id], references: [id]) user_id Int @@ -443,9 +306,8 @@ model TeamScore { score Float freemod Boolean @default(false) - map MapInMatch @relation(fields: [map_identifier, match_id], references: [map_identifier, match_id]) - map_identifier String - match_id Int + block MatchBlock @relation(fields: [block_id], references: [id]) + block_id Int team Team @relation(fields: [team_id], references: [id]) team_id Int @@ -461,20 +323,3 @@ model MappoolInMatch { @@id([mappool_id, match_id]) } - -model QualifierMatch { - id Int @id @default(autoincrement()) - teams TeamInQualifierMatch[] - map_index Int @default(0) - - map_list MapInMatch[] -} - -model TeamInQualifierMatch { - team Team @relation(fields: [team_id], references: [id]) - team_id Int - match QualifierMatch @relation(fields: [match_id], references: [id]) - match_id Int - - @@id([team_id, match_id]) -} From 80067332018fa23b11568c1e4bf8ae46fc845803 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sat, 1 Jun 2024 16:47:41 -0400 Subject: [PATCH 02/11] add 'gamemode' property to tournament settings --- prisma/schema.prisma | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index de239db..4ae3f75 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -73,6 +73,8 @@ model Tournament { model TournamentSettings { id Int @id @default(autoincrement()) + gamemode Int @default(0) // 0: std, 1: taiko, 2: catch, 3: mania + force_nf Boolean score_mode Int team_mode Int From d86c2c568d97c93fdc74d7528501ffb799f99559 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sat, 1 Jun 2024 21:39:19 -0400 Subject: [PATCH 03/11] drizzle schema --- bun.lockb | Bin 170915 -> 207920 bytes drizzle.config.ts | 12 + package.json | 3 + src/lib/drizzle/0000_married_human_fly.sql | 260 +++ src/lib/drizzle/meta/0000_snapshot.json | 1773 ++++++++++++++++++++ src/lib/drizzle/meta/_journal.json | 13 + src/lib/drizzle/relations.ts | 215 +++ src/lib/drizzle/schema.ts | 354 ++++ 8 files changed, 2630 insertions(+) create mode 100644 drizzle.config.ts create mode 100644 src/lib/drizzle/0000_married_human_fly.sql create mode 100644 src/lib/drizzle/meta/0000_snapshot.json create mode 100644 src/lib/drizzle/meta/_journal.json create mode 100644 src/lib/drizzle/relations.ts create mode 100644 src/lib/drizzle/schema.ts diff --git a/bun.lockb b/bun.lockb index 051c499a9fe56c66f88fca7245f1c5ea5574203d..bb3c0f649739979a81f9ed5936d715082edbf801 100755 GIT binary patch delta 61229 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

c?fqqvww>8XsEp2Rj=zj~fYTyPR9u;0 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 AumAu6 diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..6309a5c --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,12 @@ +import 'dotenv/config' +import { defineConfig } from 'drizzle-kit'; + +export default defineConfig({ + dialect: 'sqlite', + out: './src/lib/drizzle', + dbCredentials: { + url: 'file:../yagami-db/dev.db' + }, + verbose: true, + strict: true +}) \ No newline at end of file diff --git a/package.json b/package.json index fb13055..14c91a6 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/parser": "^6.5.0", "bun-types": "^1.0.2", + "drizzle-kit": "^0.22.1", "eslint": "^8.48.0", "nodemon": "^3.0.1", "prettier": "^3.0.3", @@ -32,8 +33,10 @@ }, "dependencies": { "@elysiajs/swagger": "^0.7.1", + "@libsql/client": "^0.6.2", "@prisma/client": "5.3.1", "dotenv": "^16.3.1", + "drizzle-orm": "^0.31.0", "elysia": "^0.7.3", "elysia-autoroutes": "^0.2.2", "express": "^4.18.2", diff --git a/src/lib/drizzle/0000_married_human_fly.sql b/src/lib/drizzle/0000_married_human_fly.sql new file mode 100644 index 0000000..79c6de9 --- /dev/null +++ b/src/lib/drizzle/0000_married_human_fly.sql @@ -0,0 +1,260 @@ +-- Current sql file was generated after introspecting the database +-- If you want to run this migration please uncomment this code before executing migrations +/* +CREATE TABLE `_prisma_migrations` ( + `id` text PRIMARY KEY NOT NULL, + `checksum` text NOT NULL, + `finished_at` numeric, + `migration_name` text NOT NULL, + `logs` text, + `rolled_back_at` numeric, + `started_at` numeric DEFAULT (current_timestamp) NOT NULL, + `applied_steps_count` integer DEFAULT 0 NOT NULL +); +--> statement-breakpoint +CREATE TABLE `Tournament` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text NOT NULL, + `acronym` text NOT NULL, + `allow_registrations` numeric DEFAULT true NOT NULL, + `private` numeric DEFAULT false NOT NULL, + `color` text, + `banner_url` text, + `description` text, + `icon_url` text +); +--> statement-breakpoint +CREATE TABLE `TournamentSettings` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `gamemode` integer DEFAULT 0 NOT NULL, + `force_nf` numeric NOT NULL, + `score_mode` integer NOT NULL, + `team_mode` integer NOT NULL, + `team_size` integer NOT NULL, + `x_v_x_mode` integer NOT NULL, + `fm_mods` integer DEFAULT 1 NOT NULL, + `double_pick` integer DEFAULT 1 NOT NULL, + `double_ban` integer DEFAULT 1 NOT NULL, + `tournament_id` integer, + `match_id` integer, + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE set null +); +--> statement-breakpoint +CREATE TABLE `ModMultiplier` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `mod_string` text NOT NULL, + `match_exactly` numeric DEFAULT false NOT NULL, + `multiplier` real NOT NULL +); +--> statement-breakpoint +CREATE TABLE `Round` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `acronym` text NOT NULL, + `name` text NOT NULL, + `tournament_id` integer NOT NULL, + FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `MappoolInRound` ( + `mappool_id` integer NOT NULL, + `round_id` integer NOT NULL, + PRIMARY KEY(`mappool_id`, `round_id`), + FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `Mappool` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text NOT NULL, + `public` numeric DEFAULT false NOT NULL +); +--> statement-breakpoint +CREATE TABLE `MapInPool` ( + `identifier` text NOT NULL, + `mods` text NOT NULL, + `map_id` integer, + `map_order` integer, + `mappool_id` integer NOT NULL, + `tournamentSettingsId` integer, + PRIMARY KEY(`identifier`, `mappool_id`), + FOREIGN KEY (`tournamentSettingsId`) REFERENCES `TournamentSettings`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`map_id`) REFERENCES `Map`(`id`) ON UPDATE cascade ON DELETE set null +); +--> statement-breakpoint +CREATE TABLE `Map` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `beatmapset_id` integer NOT NULL, + `title` text NOT NULL, + `artist` text NOT NULL, + `difficulty_name` text NOT NULL, + `url` text NOT NULL, + `cover_url` text NOT NULL, + `status` text NOT NULL, + `total_length` integer NOT NULL, + `max_combo` integer NOT NULL, + `bpm` real NOT NULL, + `last_updated` numeric NOT NULL, + `cs` real NOT NULL, + `ar` real NOT NULL, + `od` real NOT NULL, + `hp` real NOT NULL, + `star_rating` real NOT NULL, + `star_rating_dt` real, + `star_rating_hr` real, + `star_rating_ez` real, + `star_rating_ht` real, + `available` numeric NOT NULL, + `fetch_time` numeric DEFAULT (CURRENT_TIMESTAMP) NOT NULL +); +--> statement-breakpoint +CREATE TABLE `OsuOauth` ( + `user_id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `last_update` numeric DEFAULT (CURRENT_TIMESTAMP) NOT NULL, + `access_token` text NOT NULL, + `expires_in` integer NOT NULL, + `refresh_token` text NOT NULL, + `token_type` text NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `User` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `username` text NOT NULL, + `country_code` text NOT NULL, + `country_name` text NOT NULL, + `cover_url` text NOT NULL, + `ranked_score` integer NOT NULL, + `play_count` integer NOT NULL, + `total_score` integer NOT NULL, + `pp_rank` integer NOT NULL, + `level` integer NOT NULL, + `level_progress` integer NOT NULL, + `hit_accuracy` real NOT NULL, + `pp` real NOT NULL +); +--> statement-breakpoint +CREATE TABLE `UserInTeam` ( + `osu_id` integer NOT NULL, + `team_id` integer NOT NULL, + `member_order` integer DEFAULT 0 NOT NULL, + PRIMARY KEY(`osu_id`, `team_id`), + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`osu_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `Team` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text NOT NULL, + `icon_url` text NOT NULL, + `color` text NOT NULL, + `tournament_id` integer NOT NULL, + `timezone` integer, + FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `TeamInvite` ( + `invitee_user_id` integer NOT NULL, + `team_id` integer NOT NULL, + PRIMARY KEY(`invitee_user_id`, `team_id`), + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`invitee_user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `Match` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `start_time` numeric, + `mp_link` text, + `round_id` integer, + `waiting_on` integer, + `current_section` integer NOT NULL, + `block_in_section` integer NOT NULL, + `scrim` numeric DEFAULT false NOT NULL, + FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE set null +); +--> statement-breakpoint +CREATE TABLE `BlockSection` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `match_id` integer NOT NULL, + `action` text NOT NULL, + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `MatchBlock` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `section_id` integer NOT NULL, + `action` text NOT NULL, + `map_identifier` text, + `pool_id` integer, + `acted_on_by_id` integer NOT NULL, + FOREIGN KEY (`acted_on_by_id`) REFERENCES `TeamInMatch`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`map_identifier`,`pool_id`) REFERENCES `MapInPool`(`identifier`,`mappool_id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`section_id`,`action`) REFERENCES `BlockSection`(`id`,`action`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `TeamInMatch` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `match_id` integer NOT NULL, + `team_id` integer, + `score` integer NOT NULL, + `roll` integer, + `aborts` integer DEFAULT 0 NOT NULL, + `faults` integer DEFAULT 0 NOT NULL, + `winner` numeric, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `Score` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `score` real NOT NULL, + `mods` text DEFAULT '' NOT NULL, + `block_id` integer NOT NULL, + `user_id` integer NOT NULL, + `team_score_id` integer, + FOREIGN KEY (`team_score_id`) REFERENCES `TeamScore`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `TeamScore` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `score` real NOT NULL, + `freemod` numeric DEFAULT false NOT NULL, + `block_id` integer NOT NULL, + `team_id` integer NOT NULL, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `MappoolInMatch` ( + `mappool_id` integer NOT NULL, + `match_id` integer NOT NULL, + PRIMARY KEY(`mappool_id`, `match_id`), + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE restrict +); +--> statement-breakpoint +CREATE TABLE `_TournamentToUser` ( + `A` integer NOT NULL, + `B` integer NOT NULL, + FOREIGN KEY (`B`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`A`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `_ModMultiplierToSettings` ( + `A` integer NOT NULL, + `B` integer NOT NULL, + FOREIGN KEY (`B`) REFERENCES `TournamentSettings`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`A`) REFERENCES `ModMultiplier`(`id`) ON UPDATE cascade ON DELETE cascade +); +--> statement-breakpoint +CREATE UNIQUE INDEX `TournamentSettings_match_id_key` ON `TournamentSettings` (`match_id`);--> statement-breakpoint +CREATE UNIQUE INDEX `TournamentSettings_tournament_id_key` ON `TournamentSettings` (`tournament_id`);--> statement-breakpoint +CREATE UNIQUE INDEX `BlockSection_id_action_key` ON `BlockSection` (`id`,`action`);--> statement-breakpoint +CREATE INDEX `_TournamentToUser_B_index` ON `_TournamentToUser` (`B`);--> statement-breakpoint +CREATE UNIQUE INDEX `_TournamentToUser_AB_unique` ON `_TournamentToUser` (`A`,`B`);--> statement-breakpoint +CREATE INDEX `_ModMultiplierToSettings_B_index` ON `_ModMultiplierToSettings` (`B`);--> statement-breakpoint +CREATE UNIQUE INDEX `_ModMultiplierToSettings_AB_unique` ON `_ModMultiplierToSettings` (`A`,`B`); +*/ \ No newline at end of file diff --git a/src/lib/drizzle/meta/0000_snapshot.json b/src/lib/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..2b0d582 --- /dev/null +++ b/src/lib/drizzle/meta/0000_snapshot.json @@ -0,0 +1,1773 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "prevId": "", + "version": "6", + "dialect": "sqlite", + "tables": { + "_prisma_migrations": { + "name": "_prisma_migrations", + "columns": { + "id": { + "autoincrement": false, + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "checksum": { + "autoincrement": false, + "name": "checksum", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "finished_at": { + "autoincrement": false, + "name": "finished_at", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "migration_name": { + "autoincrement": false, + "name": "migration_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logs": { + "autoincrement": false, + "name": "logs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rolled_back_at": { + "autoincrement": false, + "name": "rolled_back_at", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "default": "(current_timestamp)", + "autoincrement": false, + "name": "started_at", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "applied_steps_count": { + "default": 0, + "autoincrement": false, + "name": "applied_steps_count", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "Tournament": { + "name": "Tournament", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "name": { + "autoincrement": false, + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "acronym": { + "autoincrement": false, + "name": "acronym", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allow_registrations": { + "default": true, + "autoincrement": false, + "name": "allow_registrations", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "private": { + "default": false, + "autoincrement": false, + "name": "private", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "color": { + "autoincrement": false, + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banner_url": { + "autoincrement": false, + "name": "banner_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "autoincrement": false, + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon_url": { + "autoincrement": false, + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "TournamentSettings": { + "name": "TournamentSettings", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "gamemode": { + "default": 0, + "autoincrement": false, + "name": "gamemode", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "force_nf": { + "autoincrement": false, + "name": "force_nf", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "score_mode": { + "autoincrement": false, + "name": "score_mode", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_mode": { + "autoincrement": false, + "name": "team_mode", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_size": { + "autoincrement": false, + "name": "team_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "x_v_x_mode": { + "autoincrement": false, + "name": "x_v_x_mode", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "fm_mods": { + "default": 1, + "autoincrement": false, + "name": "fm_mods", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "double_pick": { + "default": 1, + "autoincrement": false, + "name": "double_pick", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "double_ban": { + "default": 1, + "autoincrement": false, + "name": "double_ban", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tournament_id": { + "autoincrement": false, + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "match_id": { + "autoincrement": false, + "name": "match_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": { + "TournamentSettings_match_id_key": { + "name": "TournamentSettings_match_id_key", + "columns": [ + "match_id" + ], + "isUnique": true + }, + "TournamentSettings_tournament_id_key": { + "name": "TournamentSettings_tournament_id_key", + "columns": [ + "tournament_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "TournamentSettings_match_id_Match_id_fk": { + "name": "TournamentSettings_match_id_Match_id_fk", + "tableFrom": "TournamentSettings", + "tableTo": "Match", + "columnsFrom": [ + "match_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "TournamentSettings_tournament_id_Tournament_id_fk": { + "name": "TournamentSettings_tournament_id_Tournament_id_fk", + "tableFrom": "TournamentSettings", + "tableTo": "Tournament", + "columnsFrom": [ + "tournament_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "ModMultiplier": { + "name": "ModMultiplier", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "mod_string": { + "autoincrement": false, + "name": "mod_string", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "match_exactly": { + "default": false, + "autoincrement": false, + "name": "match_exactly", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "multiplier": { + "autoincrement": false, + "name": "multiplier", + "type": "real", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "Round": { + "name": "Round", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "acronym": { + "autoincrement": false, + "name": "acronym", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "autoincrement": false, + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tournament_id": { + "autoincrement": false, + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "Round_tournament_id_Tournament_id_fk": { + "name": "Round_tournament_id_Tournament_id_fk", + "tableFrom": "Round", + "tableTo": "Tournament", + "columnsFrom": [ + "tournament_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "MappoolInRound": { + "name": "MappoolInRound", + "columns": { + "mappool_id": { + "autoincrement": false, + "name": "mappool_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "round_id": { + "autoincrement": false, + "name": "round_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": { + "MappoolInRound_mappool_id_round_id_pk": { + "columns": [ + "mappool_id", + "round_id" + ], + "name": "MappoolInRound_mappool_id_round_id_pk" + } + }, + "indexes": {}, + "foreignKeys": { + "MappoolInRound_round_id_Round_id_fk": { + "name": "MappoolInRound_round_id_Round_id_fk", + "tableFrom": "MappoolInRound", + "tableTo": "Round", + "columnsFrom": [ + "round_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "MappoolInRound_mappool_id_Mappool_id_fk": { + "name": "MappoolInRound_mappool_id_Mappool_id_fk", + "tableFrom": "MappoolInRound", + "tableTo": "Mappool", + "columnsFrom": [ + "mappool_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "Mappool": { + "name": "Mappool", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "name": { + "autoincrement": false, + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "public": { + "default": false, + "autoincrement": false, + "name": "public", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "MapInPool": { + "name": "MapInPool", + "columns": { + "identifier": { + "autoincrement": false, + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "mods": { + "autoincrement": false, + "name": "mods", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "map_id": { + "autoincrement": false, + "name": "map_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "map_order": { + "autoincrement": false, + "name": "map_order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "mappool_id": { + "autoincrement": false, + "name": "mappool_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tournamentSettingsId": { + "autoincrement": false, + "name": "tournamentSettingsId", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": { + "MapInPool_identifier_mappool_id_pk": { + "columns": [ + "identifier", + "mappool_id" + ], + "name": "MapInPool_identifier_mappool_id_pk" + } + }, + "indexes": {}, + "foreignKeys": { + "MapInPool_tournamentSettingsId_TournamentSettings_id_fk": { + "name": "MapInPool_tournamentSettingsId_TournamentSettings_id_fk", + "tableFrom": "MapInPool", + "tableTo": "TournamentSettings", + "columnsFrom": [ + "tournamentSettingsId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "MapInPool_mappool_id_Mappool_id_fk": { + "name": "MapInPool_mappool_id_Mappool_id_fk", + "tableFrom": "MapInPool", + "tableTo": "Mappool", + "columnsFrom": [ + "mappool_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "MapInPool_map_id_Map_id_fk": { + "name": "MapInPool_map_id_Map_id_fk", + "tableFrom": "MapInPool", + "tableTo": "Map", + "columnsFrom": [ + "map_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "Map": { + "name": "Map", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "beatmapset_id": { + "autoincrement": false, + "name": "beatmapset_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "title": { + "autoincrement": false, + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "artist": { + "autoincrement": false, + "name": "artist", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "difficulty_name": { + "autoincrement": false, + "name": "difficulty_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "autoincrement": false, + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cover_url": { + "autoincrement": false, + "name": "cover_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "autoincrement": false, + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_length": { + "autoincrement": false, + "name": "total_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "max_combo": { + "autoincrement": false, + "name": "max_combo", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "bpm": { + "autoincrement": false, + "name": "bpm", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "last_updated": { + "autoincrement": false, + "name": "last_updated", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "cs": { + "autoincrement": false, + "name": "cs", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "ar": { + "autoincrement": false, + "name": "ar", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "od": { + "autoincrement": false, + "name": "od", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "hp": { + "autoincrement": false, + "name": "hp", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "star_rating": { + "autoincrement": false, + "name": "star_rating", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "star_rating_dt": { + "autoincrement": false, + "name": "star_rating_dt", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "star_rating_hr": { + "autoincrement": false, + "name": "star_rating_hr", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "star_rating_ez": { + "autoincrement": false, + "name": "star_rating_ez", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "star_rating_ht": { + "autoincrement": false, + "name": "star_rating_ht", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "available": { + "autoincrement": false, + "name": "available", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "fetch_time": { + "default": "(CURRENT_TIMESTAMP)", + "autoincrement": false, + "name": "fetch_time", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "OsuOauth": { + "name": "OsuOauth", + "columns": { + "user_id": { + "autoincrement": true, + "name": "user_id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "last_update": { + "default": "(CURRENT_TIMESTAMP)", + "autoincrement": false, + "name": "last_update", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "autoincrement": false, + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_in": { + "autoincrement": false, + "name": "expires_in", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "autoincrement": false, + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_type": { + "autoincrement": false, + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "OsuOauth_user_id_User_id_fk": { + "name": "OsuOauth_user_id_User_id_fk", + "tableFrom": "OsuOauth", + "tableTo": "User", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "User": { + "name": "User", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "username": { + "autoincrement": false, + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "country_code": { + "autoincrement": false, + "name": "country_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "country_name": { + "autoincrement": false, + "name": "country_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cover_url": { + "autoincrement": false, + "name": "cover_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ranked_score": { + "autoincrement": false, + "name": "ranked_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "play_count": { + "autoincrement": false, + "name": "play_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "total_score": { + "autoincrement": false, + "name": "total_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "pp_rank": { + "autoincrement": false, + "name": "pp_rank", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "level": { + "autoincrement": false, + "name": "level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "level_progress": { + "autoincrement": false, + "name": "level_progress", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "hit_accuracy": { + "autoincrement": false, + "name": "hit_accuracy", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "pp": { + "autoincrement": false, + "name": "pp", + "type": "real", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {} + }, + "UserInTeam": { + "name": "UserInTeam", + "columns": { + "osu_id": { + "autoincrement": false, + "name": "osu_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "autoincrement": false, + "name": "team_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "member_order": { + "default": 0, + "autoincrement": false, + "name": "member_order", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": { + "UserInTeam_osu_id_team_id_pk": { + "columns": [ + "osu_id", + "team_id" + ], + "name": "UserInTeam_osu_id_team_id_pk" + } + }, + "indexes": {}, + "foreignKeys": { + "UserInTeam_team_id_Team_id_fk": { + "name": "UserInTeam_team_id_Team_id_fk", + "tableFrom": "UserInTeam", + "tableTo": "Team", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "UserInTeam_osu_id_User_id_fk": { + "name": "UserInTeam_osu_id_User_id_fk", + "tableFrom": "UserInTeam", + "tableTo": "User", + "columnsFrom": [ + "osu_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "Team": { + "name": "Team", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "name": { + "autoincrement": false, + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "icon_url": { + "autoincrement": false, + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "autoincrement": false, + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tournament_id": { + "autoincrement": false, + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "autoincrement": false, + "name": "timezone", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "Team_tournament_id_Tournament_id_fk": { + "name": "Team_tournament_id_Tournament_id_fk", + "tableFrom": "Team", + "tableTo": "Tournament", + "columnsFrom": [ + "tournament_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "TeamInvite": { + "name": "TeamInvite", + "columns": { + "invitee_user_id": { + "autoincrement": false, + "name": "invitee_user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "autoincrement": false, + "name": "team_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": { + "TeamInvite_invitee_user_id_team_id_pk": { + "columns": [ + "invitee_user_id", + "team_id" + ], + "name": "TeamInvite_invitee_user_id_team_id_pk" + } + }, + "indexes": {}, + "foreignKeys": { + "TeamInvite_team_id_Team_id_fk": { + "name": "TeamInvite_team_id_Team_id_fk", + "tableFrom": "TeamInvite", + "tableTo": "Team", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "TeamInvite_invitee_user_id_User_id_fk": { + "name": "TeamInvite_invitee_user_id_User_id_fk", + "tableFrom": "TeamInvite", + "tableTo": "User", + "columnsFrom": [ + "invitee_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "Match": { + "name": "Match", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "start_time": { + "autoincrement": false, + "name": "start_time", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "mp_link": { + "autoincrement": false, + "name": "mp_link", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "round_id": { + "autoincrement": false, + "name": "round_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "waiting_on": { + "autoincrement": false, + "name": "waiting_on", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "current_section": { + "autoincrement": false, + "name": "current_section", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "block_in_section": { + "autoincrement": false, + "name": "block_in_section", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "scrim": { + "default": false, + "autoincrement": false, + "name": "scrim", + "type": "numeric", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "Match_round_id_Round_id_fk": { + "name": "Match_round_id_Round_id_fk", + "tableFrom": "Match", + "tableTo": "Round", + "columnsFrom": [ + "round_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "BlockSection": { + "name": "BlockSection", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "match_id": { + "autoincrement": false, + "name": "match_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "action": { + "autoincrement": false, + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": { + "BlockSection_id_action_key": { + "name": "BlockSection_id_action_key", + "columns": [ + "id", + "action" + ], + "isUnique": true + } + }, + "foreignKeys": { + "BlockSection_match_id_Match_id_fk": { + "name": "BlockSection_match_id_Match_id_fk", + "tableFrom": "BlockSection", + "tableTo": "Match", + "columnsFrom": [ + "match_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "MatchBlock": { + "name": "MatchBlock", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "section_id": { + "autoincrement": false, + "name": "section_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "action": { + "autoincrement": false, + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "map_identifier": { + "autoincrement": false, + "name": "map_identifier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pool_id": { + "autoincrement": false, + "name": "pool_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "acted_on_by_id": { + "autoincrement": false, + "name": "acted_on_by_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "MatchBlock_acted_on_by_id_TeamInMatch_id_fk": { + "name": "MatchBlock_acted_on_by_id_TeamInMatch_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "TeamInMatch", + "columnsFrom": [ + "acted_on_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "MatchBlock_map_identifier_pool_id_MapInPool_identifier_mappool_id_fk": { + "name": "MatchBlock_map_identifier_pool_id_MapInPool_identifier_mappool_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "MapInPool", + "columnsFrom": [ + "map_identifier", + "pool_id" + ], + "columnsTo": [ + "identifier", + "mappool_id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "MatchBlock_section_id_action_BlockSection_id_action_fk": { + "name": "MatchBlock_section_id_action_BlockSection_id_action_fk", + "tableFrom": "MatchBlock", + "tableTo": "BlockSection", + "columnsFrom": [ + "section_id", + "action" + ], + "columnsTo": [ + "id", + "action" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "TeamInMatch": { + "name": "TeamInMatch", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "match_id": { + "autoincrement": false, + "name": "match_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "autoincrement": false, + "name": "team_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "score": { + "autoincrement": false, + "name": "score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "roll": { + "autoincrement": false, + "name": "roll", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "aborts": { + "default": 0, + "autoincrement": false, + "name": "aborts", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "faults": { + "default": 0, + "autoincrement": false, + "name": "faults", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "winner": { + "autoincrement": false, + "name": "winner", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "TeamInMatch_team_id_Team_id_fk": { + "name": "TeamInMatch_team_id_Team_id_fk", + "tableFrom": "TeamInMatch", + "tableTo": "Team", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "TeamInMatch_match_id_Match_id_fk": { + "name": "TeamInMatch_match_id_Match_id_fk", + "tableFrom": "TeamInMatch", + "tableTo": "Match", + "columnsFrom": [ + "match_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "Score": { + "name": "Score", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "score": { + "autoincrement": false, + "name": "score", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "mods": { + "default": "''", + "autoincrement": false, + "name": "mods", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "autoincrement": false, + "name": "block_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "autoincrement": false, + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_score_id": { + "autoincrement": false, + "name": "team_score_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "Score_team_score_id_TeamScore_id_fk": { + "name": "Score_team_score_id_TeamScore_id_fk", + "tableFrom": "Score", + "tableTo": "TeamScore", + "columnsFrom": [ + "team_score_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "Score_user_id_User_id_fk": { + "name": "Score_user_id_User_id_fk", + "tableFrom": "Score", + "tableTo": "User", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "Score_block_id_MatchBlock_id_fk": { + "name": "Score_block_id_MatchBlock_id_fk", + "tableFrom": "Score", + "tableTo": "MatchBlock", + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "TeamScore": { + "name": "TeamScore", + "columns": { + "id": { + "autoincrement": true, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true + }, + "score": { + "autoincrement": false, + "name": "score", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "freemod": { + "default": false, + "autoincrement": false, + "name": "freemod", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "autoincrement": false, + "name": "block_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "autoincrement": false, + "name": "team_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "TeamScore_team_id_Team_id_fk": { + "name": "TeamScore_team_id_Team_id_fk", + "tableFrom": "TeamScore", + "tableTo": "Team", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "TeamScore_block_id_MatchBlock_id_fk": { + "name": "TeamScore_block_id_MatchBlock_id_fk", + "tableFrom": "TeamScore", + "tableTo": "MatchBlock", + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "MappoolInMatch": { + "name": "MappoolInMatch", + "columns": { + "mappool_id": { + "autoincrement": false, + "name": "mappool_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "match_id": { + "autoincrement": false, + "name": "match_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": { + "MappoolInMatch_mappool_id_match_id_pk": { + "columns": [ + "mappool_id", + "match_id" + ], + "name": "MappoolInMatch_mappool_id_match_id_pk" + } + }, + "indexes": {}, + "foreignKeys": { + "MappoolInMatch_match_id_Match_id_fk": { + "name": "MappoolInMatch_match_id_Match_id_fk", + "tableFrom": "MappoolInMatch", + "tableTo": "Match", + "columnsFrom": [ + "match_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "MappoolInMatch_mappool_id_Mappool_id_fk": { + "name": "MappoolInMatch_mappool_id_Mappool_id_fk", + "tableFrom": "MappoolInMatch", + "tableTo": "Mappool", + "columnsFrom": [ + "mappool_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "_TournamentToUser": { + "name": "_TournamentToUser", + "columns": { + "A": { + "autoincrement": false, + "name": "A", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "B": { + "autoincrement": false, + "name": "B", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": { + "_TournamentToUser_B_index": { + "name": "_TournamentToUser_B_index", + "columns": [ + "B" + ], + "isUnique": false + }, + "_TournamentToUser_AB_unique": { + "name": "_TournamentToUser_AB_unique", + "columns": [ + "A", + "B" + ], + "isUnique": true + } + }, + "foreignKeys": { + "_TournamentToUser_B_User_id_fk": { + "name": "_TournamentToUser_B_User_id_fk", + "tableFrom": "_TournamentToUser", + "tableTo": "User", + "columnsFrom": [ + "B" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "_TournamentToUser_A_Tournament_id_fk": { + "name": "_TournamentToUser_A_Tournament_id_fk", + "tableFrom": "_TournamentToUser", + "tableTo": "Tournament", + "columnsFrom": [ + "A" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + }, + "_ModMultiplierToSettings": { + "name": "_ModMultiplierToSettings", + "columns": { + "A": { + "autoincrement": false, + "name": "A", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "B": { + "autoincrement": false, + "name": "B", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": { + "_ModMultiplierToSettings_B_index": { + "name": "_ModMultiplierToSettings_B_index", + "columns": [ + "B" + ], + "isUnique": false + }, + "_ModMultiplierToSettings_AB_unique": { + "name": "_ModMultiplierToSettings_AB_unique", + "columns": [ + "A", + "B" + ], + "isUnique": true + } + }, + "foreignKeys": { + "_ModMultiplierToSettings_B_TournamentSettings_id_fk": { + "name": "_ModMultiplierToSettings_B_TournamentSettings_id_fk", + "tableFrom": "_ModMultiplierToSettings", + "tableTo": "TournamentSettings", + "columnsFrom": [ + "B" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "_ModMultiplierToSettings_A_ModMultiplier_id_fk": { + "name": "_ModMultiplierToSettings_A_ModMultiplier_id_fk", + "tableFrom": "_ModMultiplierToSettings", + "tableTo": "ModMultiplier", + "columnsFrom": [ + "A" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/src/lib/drizzle/meta/_journal.json b/src/lib/drizzle/meta/_journal.json new file mode 100644 index 0000000..e4cf9b3 --- /dev/null +++ b/src/lib/drizzle/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "6", + "when": 1717281455192, + "tag": "0000_married_human_fly", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/src/lib/drizzle/relations.ts b/src/lib/drizzle/relations.ts new file mode 100644 index 0000000..33566c7 --- /dev/null +++ b/src/lib/drizzle/relations.ts @@ -0,0 +1,215 @@ +import { relations } from "drizzle-orm/relations"; +import { Match, Settings, Tournament, Round, MappoolInRound, Mappool, MapInPool, Map, User, OsuOauth, Team, UserInTeam, BlockSection, TeamInMatch, MatchBlock, TeamScore, Score, ModMultiplier, MapStats, TeamInTournament } from "./schema"; + + +export const TournamentRelations = relations(Tournament, ({ one, many }) => ({ + rounds: many(Round), + team_list: many(TeamInTournament), + + settings: one(Settings, { + fields: [Tournament.settings_id], + references: [Settings.id] + }), +})); + +export const SettingsRelations = relations(Settings, ({ many }) => ({ + applied_to_tournament: many(Tournament), + applied_to_matches: many(Match), + applied_to_maps: many(MapInPool), +})); + +export const ModMultiplierRelations = relations(ModMultiplier, ({ one }) => ({ + settings: one(Settings, { + fields: [ModMultiplier.settings_id], + references: [Settings.id] + }), +})); + +export const RoundRelations = relations(Round, ({ one, many }) => ({ + tournament: one(Tournament, { + fields: [Round.tournament_id], + references: [Tournament.id] + }), + mappool_list: many(MappoolInRound), + matches: many(Match), +})); + +export const MappoolInRoundRelations = relations(MappoolInRound, ({ one }) => ({ + round: one(Round, { + fields: [MappoolInRound.round_id], + references: [Round.id] + }), + mappool: one(Mappool, { + fields: [MappoolInRound.mappool_id], + references: [Mappool.id] + }), +})); + +export const MappoolRelations = relations(Mappool, ({ many }) => ({ + rounds_list: many(MappoolInRound), + maps_in_pool: many(MapInPool), + section_list: many(BlockSection), +})); + +export const MapInPoolRelations = relations(MapInPool, ({ one, many }) => ({ + mappool: one(Mappool, { + fields: [MapInPool.mappool_id], + references: [Mappool.id] + }), + settings: one(Settings, { + fields: [MapInPool.settings_id], + references: [Settings.id] + }), + map_data: one(Map, { + fields: [MapInPool.map_id], + references: [Map.id] + }), + + used_in: many(MatchBlock), +})); + +export const MapRelations = relations(Map, ({ many }) => ({ + in_pools: many(MapInPool), + stats: many(MapStats) +})); + +export const MapStatsRelations = relations(MapStats, ({ one }) => ({ + for_map: one(Map, { + fields: [MapStats.map_id], + references: [Map.id] + }) +})) + +export const OsuOauthRelations = relations(OsuOauth, ({ one }) => ({ + user: one(User, { + fields: [OsuOauth.user_id], + references: [User.id] + }), +})); + +export const UserRelations = relations(User, ({ many, one }) => ({ + token: one(OsuOauth, { + fields: [User.id], + references: [OsuOauth.user_id] + }), + in_teams_list: many(UserInTeam), + scores: many(Score), +})); + +export const UserInTeamRelations = relations(UserInTeam, ({ one }) => ({ + team: one(Team, { + fields: [UserInTeam.team_id], + references: [Team.id] + }), + user: one(User, { + fields: [UserInTeam.user_id], + references: [User.id] + }), +})); + +export const TeamRelations = relations(Team, ({ many }) => ({ + tournament_list: many(TeamInTournament), + user_list: many(UserInTeam), + match_list: many(TeamInMatch), + team_scores: many(TeamScore), +})); + +export const TeamInTournamentRelations = relations(TeamInTournament, ({ one }) => ({ + tournament: one(Tournament, { + fields: [TeamInTournament.tournament_id], + references: [Tournament.id] + }), + team: one(Team, { + fields: [TeamInTournament.team_id], + references: [Team.id] + }) +})) + +export const MatchRelations = relations(Match, ({ one, many }) => ({ + settings: one(Settings, { + fields: [Match.settings_id], + references: [Settings.id] + }), + round: one(Round, { + fields: [Match.round_id], + references: [Round.id] + }), + sections: many(BlockSection, { relationName: 'section_list' }), + team_list: many(TeamInMatch, { relationName: 'team_list' }), + + // Match state + current_section: one(BlockSection, { + fields: [Match.current_section_id], + references: [BlockSection.id], + relationName: "current_section" + }), + current_block: one(MatchBlock, { + fields: [Match.current_block_id], + references: [MatchBlock.id], + relationName: "current_block" + }) +})); + +export const BlockSectionRelations = relations(BlockSection, ({ one, many }) => ({ + for_match: one(Match, { + fields: [BlockSection.match_id], + references: [Match.id] + }), + blocks: many(MatchBlock), +})); + +export const MatchBlockRelations = relations(MatchBlock, ({ one, many }) => ({ + actor_team: one(TeamInMatch, { + fields: [MatchBlock.acted_on_by_id], + references: [TeamInMatch.id] + }), + map: one(MapInPool, { + fields: [MatchBlock.map_identifier, MatchBlock.pool_id], + references: [MapInPool.identifier, MapInPool.mappool_id] + }), + BlockSection: one(BlockSection, { + fields: [MatchBlock.section_id], + references: [BlockSection.id] + }), + Scores: many(Score), + TeamScores: many(TeamScore), +})); + +export const TeamInMatchRelations = relations(TeamInMatch, ({ one, many }) => ({ + acted_on: many(MatchBlock), + team: one(Team, { + fields: [TeamInMatch.team_id], + references: [Team.id] + }), + match: one(Match, { + fields: [TeamInMatch.match_id], + references: [Match.id] + }), +})); + +export const ScoreRelations = relations(Score, ({ one }) => ({ + score_for: one(TeamScore, { + fields: [Score.team_score_id], + references: [TeamScore.id] + }), + user: one(User, { + fields: [Score.user_id], + references: [User.id] + }), + for_block: one(MatchBlock, { + fields: [Score.block_id], + references: [MatchBlock.id] + }), +})); + +export const TeamScoreRelations = relations(TeamScore, ({ one, many }) => ({ + user_scores: many(Score), + team: one(Team, { + fields: [TeamScore.team_id], + references: [Team.id] + }), + match: one(MatchBlock, { + fields: [TeamScore.block_id], + references: [MatchBlock.id] + }), +})); \ No newline at end of file diff --git a/src/lib/drizzle/schema.ts b/src/lib/drizzle/schema.ts new file mode 100644 index 0000000..d1fa5fa --- /dev/null +++ b/src/lib/drizzle/schema.ts @@ -0,0 +1,354 @@ +import { sqliteTable, text, integer, real, primaryKey } from "drizzle-orm/sqlite-core" +import { sql } from "drizzle-orm" + +/** + * A tournament hosted on Yagami with multiple hosts. + * + * Mappools imported from external places do not have + * a tournament object. + */ +export const Tournament = sqliteTable("Tournament", { + id: integer("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull(), + acronym: text("acronym").notNull(), // Used in the MP name; [ACRONYM: (Team 1) vs (Team 2)] + + settings_id: integer("settings_id").references(() => Settings.id), + + // Registration Settings + allow_registrations: integer("allow_registrations", { mode: "boolean" }).default(true).notNull(), + private: integer("private", { mode: "boolean" }).notNull(), + team_size: integer("team_size").notNull(), + + // Optional Customization + color: text("color"), + banner_url: text("banner_url"), + description: text("description"), + icon_url: text("icon_url"), +}); + +/** + * Holds in-match settings. + * + * Can be applied: + * * Tournament-wide (for default tournament settings) + * * Match-specific (for scrims) + * * Map-specific (for per-map gimmicks like different mod multipliers) + */ +export const Settings = sqliteTable("Settings", { + id: integer("id").primaryKey({ autoIncrement: true }), + + gamemode: integer("gamemode").default(0).notNull(), // 0: std, 1: taiko, 2: catch, 3: mania + + // !mp set [team_mode] [score_mode] + team_mode: integer("team_mode").notNull(), // 0: Head to Head; 1: TagCoop; 2: TeamVS; 3: TeamTagVs + score_mode: integer("score_mode").notNull(), // 0: Score; 1: Accuracy; 2: Combo; 3: ScoreV2; 4: ScoreV2 Accuracy + + force_nf: integer("force_nf", { mode: 'boolean' }).default(true).notNull(), // Whether to add NF to every pick + fm_mods: integer("fm_mods").default(1).notNull(), // How many players need to take a mod + player_count: integer("player_count").notNull(), // How many players vs how many players + + // Foreign Keys + tournament_id: integer("tournament_id").unique().references(() => Tournament.id, { onDelete: "set null", onUpdate: "cascade" }), + match_id: integer("match_id").unique().references(() => Match.id, { onDelete: "set null", onUpdate: "cascade" }), +}); + +/** + * A custom multiplier to be applied to a FreeMod pick + * + * If some mod combination matches multiple mod multipliers, + * all multipliers are averaged, then applied. + */ +export const ModMultiplier = sqliteTable("ModMultiplier", { + id: integer("id").primaryKey({ autoIncrement: true }), + settings_id: integer("settings_id").references(() => Settings.id, { onDelete: "cascade", onUpdate: "cascade" }), + + multiplier: real("multiplier").notNull(), + + // What to match, HD, HR, HDHR etc. + mod_string: text("mod_string").notNull(), + // For example, if a player takes HDHR and the rule is HD - 0.90, rule is applied if match_exactly is false, otherwise it is ignored. + match_exactly: integer("match_exactly", { mode: 'boolean' }).notNull(), +}); + +/** + * A round in the tournament + * + * Can have multiple matches or mappools linked. + */ +export const Round = sqliteTable("Round", { + id: integer("id").primaryKey({ autoIncrement: true }), + acronym: text("acronym").notNull(), + name: text("name").notNull(), + + tournament_id: integer("tournament_id").notNull().references(() => Tournament.id, { onDelete: "cascade", onUpdate: "cascade" }), +}); + +/** + * Linker table for many-to-many relations between Mappool and Round + */ +export const MappoolInRound = sqliteTable("MappoolInRound", { + mappool_id: integer("mappool_id").notNull().references(() => Mappool.id, { onDelete: "restrict", onUpdate: "cascade" }), + round_id: integer("round_id").notNull().references(() => Round.id, { onDelete: "restrict", onUpdate: "cascade" }), +}, + (table) => ({ + composite_key: primaryKey({ columns: [table.mappool_id, table.round_id] }) + })); + +/** + * A list of maps + * + * References multiple MapInPool objects + */ +export const Mappool = sqliteTable("Mappool", { + id: integer("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull(), + public: integer("public", { mode: 'boolean' }).default(true).notNull(), +}); + +/** + * A map in a mappool + * + * Has fields for the name, (NM1, HD2 etc.), + * and references some Map object for map data. + */ +export const MapInPool = sqliteTable("MapInPool", { + identifier: text("identifier").notNull(), // NM1, NM2 etc. + + map_order: integer("map_order"), // Where this map appears in the pool (NM1 is 1, NM2 is 2 etc.) + mods: text("mods").notNull(), // !mp mods [mods] (force_nf ? "NF" : "") + + // Foreign Keys + mappool_id: integer("mappool_id").notNull().references(() => Mappool.id, { onDelete: "cascade", onUpdate: "cascade" }), + map_id: integer("map_id").references(() => Map.id, { onDelete: "set null", onUpdate: "cascade" }), + settings_id: integer("tournamentSettingsId").references(() => Settings.id, { onDelete: "set null", onUpdate: "cascade" }), +}, + (table) => ({ + composite_key: primaryKey({ columns: [table.identifier, table.mappool_id] }) + })); + +/** + * Cache object for maps from the osu!api + */ +export const Map = sqliteTable("Map", { + id: integer("id").primaryKey(), + beatmapset_id: integer("beatmapset_id").notNull(), + fetch_time: integer("fetch_time", { mode: 'timestamp_ms' }).default(sql`(CURRENT_TIMESTAMP)`).notNull(), + + // Rendered as "title - artist [difficulty_name]" in chat + title: text("title").notNull(), + artist: text("artist").notNull(), + difficulty_name: text("difficulty_name").notNull(), + + // Additional Fields for displaying nicely in a Web format. + url: text("url").notNull(), + cover_url: text("cover_url").notNull(), + status: text("status").notNull(), + max_combo: integer("max_combo").notNull(), + last_updated: integer("last_updated", { mode: 'timestamp_ms' }).notNull(), + + // Whether a user is able to download + // using osu!direct/official servers + available: integer("available", { mode: 'boolean' }).notNull(), +}); + +/** + * Represents stats about a map + * + * Linked to a Map, with some mod_string. For displaying NM stats, DT stats, etc. + * mod_string should match the string of the MapInPool object ("" means nomod) + */ +export const MapStats = sqliteTable('MapStats', { + map_id: integer('map_id',).notNull().references(() => Map.id, { onDelete: 'cascade', onUpdate: 'cascade' }), + mod_string: text('mod_string').default("").notNull(), + + star_rating: real("star_rating").notNull(), + bpm: real("bpm").notNull(), + length: integer("length").notNull(), // Length of map in seconds + + cs: real("cs").notNull(), + ar: real("ar").notNull(), + od: real("od").notNull(), + hp: real("hp").notNull(), +}, (table) => ({ + composite_key: primaryKey({ columns: [table.map_id, table.mod_string] }) +})) + +/** + * Contains a user's osu OauthV2 token. + * + * Used for updating player information, like rank &pp + */ +export const OsuOauth = sqliteTable("OsuOauth", { + user_id: integer("user_id").primaryKey().references(() => User.id, { onDelete: "cascade", onUpdate: "cascade" }), + + token_type: text("token_type").notNull(), // almost always "Bearer" + access_token: text("access_token").notNull(), + refresh_token: text("refresh_token").notNull(), + + expires_at: integer("expires_at", { mode: 'timestamp_ms' }).notNull() +}); + +/** + * Represents an osu user. + * + * id column is shared with osu! id. + */ +export const User = sqliteTable("User", { + id: integer("id").primaryKey(), + username: text("username").notNull(), + country_code: text("country_code").notNull(), + country_name: text("country_name").notNull(), + + cover_url: text("cover_url").notNull(), + avatar_url: text("avatar_url").notNull(), + + pp: real("pp"), + global_rank: integer("global_rank"), + country_rank: integer("country_rank"), + + total_score: integer("total_score"), + ranked_score: integer("ranked_score"), + hit_accuracy: real("hit_accuracy"), + play_count: integer("play_count"), + level: integer("level"), + level_progress: integer("level_progress"), +}); + + +/** + * Linker table for many-to-many relations between User and Team + * + * - When listing players in a team, ignore users with invite=true + */ +export const UserInTeam = sqliteTable("UserInTeam", { + user_id: integer("user_id").notNull().references(() => User.id, { onDelete: "cascade", onUpdate: "cascade" }), + team_id: integer("team_id").notNull().references(() => Team.id, { onDelete: "cascade", onUpdate: "cascade" }), + invite: integer("invite", { mode: 'boolean' }), // If true, the user is not a member of the team (they have been invited and have not accepted) + member_order: integer("member_order").default(0), // Where in the team the user appears. (Captain is 0, etc.) +}, + (table) => ({ + composite_key: primaryKey({ columns: [table.user_id, table.team_id] }) + })); + +/** + * Represents a Team for a tournament or scrim. + * + * - A team can be in multiple Tournaments or scrims + * - 1v1 matches still use Teams, just a Team consisting of 1 player. + */ +export const Team = sqliteTable("Team", { + id: integer("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull(), + icon_url: text("icon_url"), + color: text("color").notNull(), + timezone: integer("timezone"), +}); + +/** + * A linker table for many-to-many relations between Team and Tournament + */ +export const TeamInTournament = sqliteTable("TeamInTournament", { + tournament_id: integer("id").references(() => Tournament.id), + team_id: integer("id").references(() => Team.id), +}, (table) => ({ + composite_key: primaryKey({ columns: [table.tournament_id, table.team_id] }) +})) + +/** + * Represents a match that is or has run + * + * The state of the match is stored entirely within the database. + */ +export const Match = sqliteTable("Match", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + start_time: integer("start_time", { mode: 'timestamp_ms' }), + mp_link: text("mp_link"), + + scrim: integer("scrim", { mode: 'boolean' }).default(false).notNull(), + + // The current state of the match: + current_section_id: integer("current_section_id").notNull().references(() => BlockSection.id), // What block section are we currently on + block_in_section_id: integer("block_in_section_id").notNull().references(() => MatchBlock.id), // What block in the section are we currently on + + round_id: integer("round_id").references(() => Round.id, { onDelete: "set null", onUpdate: "cascade" }), + settings_id: integer("settings_id").references(() => Settings.id, { onDelete: "restrict", onUpdate: "cascade" }) +}); + +/** + * A set ordered blocks with some common action. + * When a team runs out of time to do some action, + * the block is moved to the end of the list. + * (MatchBlock.order_number => MatchBlocks.maxOrderNumber() + 1) + */ +export const BlockSection = sqliteTable("BlockSection", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + match_id: integer("match_id").notNull().references(() => Match.id, { onDelete: "cascade", onUpdate: "cascade" }), + mappool_id: integer("mappool_id").notNull().references(() => Mappool.id), + + action: text("action").notNull(), // PICK, BAN, PROTECT, FORCED PICK etc. +}); + +/** + * A block where something happens in a match, be it pick, ban, protect etc. + */ +export const MatchBlock = sqliteTable("MatchBlock", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + + // Which section + section_id: integer("section_id").notNull().references(() => BlockSection.id), + action: text("action").notNull().references(() => BlockSection.id), + + order_number: integer("order_number").notNull(), + + // Which map + map_identifier: text("map_identifier").references(() => MapInPool.identifier), + pool_id: integer("pool_id").references(() => MapInPool.mappool_id), + + // Who did it + acted_on_by_id: integer("acted_on_by_id").references(() => TeamInMatch.id, { onDelete: "cascade", onUpdate: "cascade" }), +}); + +/** + * A Team object that is a member of a Match + * Linker table for many-to-many relations between Team and Match + */ +export const TeamInMatch = sqliteTable("TeamInMatch", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + match_id: integer("match_id").notNull().references(() => Match.id, { onDelete: "cascade", onUpdate: "cascade" }), + team_id: integer("team_id").references(() => Team.id, { onDelete: "set null", onUpdate: "cascade" }), + + score: integer("score").notNull(), + roll: integer("roll"), + winner: integer("winner", { mode: 'boolean' }), + + // Honor System + aborts: integer("aborts").default(0).notNull(), + faults: integer("faults").default(0).notNull(), +}); + +/** + * A user's score on a map (MatchBlock) + * + * Contains references to a team score (for a team's score) + */ +export const Score = sqliteTable("Score", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + + score: real("score").notNull(), // This is stored as a real number for storing either Score or Accuracy + mods: text("mods"), // In the case of freemods + + block_id: integer("block_id").notNull().references(() => MatchBlock.id, { onDelete: "cascade", onUpdate: "cascade" }), + user_id: integer("user_id").notNull().references(() => User.id, { onDelete: "cascade", onUpdate: "cascade" }), + team_score_id: integer("team_score_id").references(() => TeamScore.id, { onDelete: "set null", onUpdate: "cascade" }), +}); + +/** + * A team's score on a map (MatchBlock) + */ +export const TeamScore = sqliteTable("TeamScore", { + id: integer("id").primaryKey({ autoIncrement: true }).notNull(), + score: real("score").notNull(), + + block_id: integer("block_id").notNull().references(() => MatchBlock.id, { onDelete: "cascade", onUpdate: "cascade" }), + team_id: integer("team_id").notNull().references(() => Team.id, { onDelete: "cascade", onUpdate: "cascade" }), +}); \ No newline at end of file From 7bb5f01c26c01f2e95bf206c7c057b09e3f24a57 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sat, 1 Jun 2024 21:50:26 -0400 Subject: [PATCH 04/11] migrate to drizzle --- drizzle.config.ts | 1 + ...ied_human_fly.sql => 0000_wild_vermin.sql} | 347 ++- src/lib/drizzle/meta/0000_snapshot.json | 2188 ++++++++--------- src/lib/drizzle/meta/_journal.json | 6 +- 4 files changed, 1178 insertions(+), 1364 deletions(-) rename src/lib/drizzle/{0000_married_human_fly.sql => 0000_wild_vermin.sql} (51%) diff --git a/drizzle.config.ts b/drizzle.config.ts index 6309a5c..408a956 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -4,6 +4,7 @@ import { defineConfig } from 'drizzle-kit'; export default defineConfig({ dialect: 'sqlite', out: './src/lib/drizzle', + schema: "./src/lib/drizzle/schema.ts", dbCredentials: { url: 'file:../yagami-db/dev.db' }, diff --git a/src/lib/drizzle/0000_married_human_fly.sql b/src/lib/drizzle/0000_wild_vermin.sql similarity index 51% rename from src/lib/drizzle/0000_married_human_fly.sql rename to src/lib/drizzle/0000_wild_vermin.sql index 79c6de9..8130c8b 100644 --- a/src/lib/drizzle/0000_married_human_fly.sql +++ b/src/lib/drizzle/0000_wild_vermin.sql @@ -1,196 +1,156 @@ --- Current sql file was generated after introspecting the database --- If you want to run this migration please uncomment this code before executing migrations -/* -CREATE TABLE `_prisma_migrations` ( - `id` text PRIMARY KEY NOT NULL, - `checksum` text NOT NULL, - `finished_at` numeric, - `migration_name` text NOT NULL, - `logs` text, - `rolled_back_at` numeric, - `started_at` numeric DEFAULT (current_timestamp) NOT NULL, - `applied_steps_count` integer DEFAULT 0 NOT NULL +CREATE TABLE `BlockSection` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `match_id` integer NOT NULL, + `mappool_id` integer NOT NULL, + `action` text NOT NULL, + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint -CREATE TABLE `Tournament` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text NOT NULL, - `acronym` text NOT NULL, - `allow_registrations` numeric DEFAULT true NOT NULL, - `private` numeric DEFAULT false NOT NULL, - `color` text, - `banner_url` text, - `description` text, - `icon_url` text +CREATE TABLE `Map` ( + `id` integer PRIMARY KEY NOT NULL, + `beatmapset_id` integer NOT NULL, + `fetch_time` integer DEFAULT (CURRENT_TIMESTAMP) NOT NULL, + `title` text NOT NULL, + `artist` text NOT NULL, + `difficulty_name` text NOT NULL, + `url` text NOT NULL, + `cover_url` text NOT NULL, + `status` text NOT NULL, + `max_combo` integer NOT NULL, + `last_updated` integer NOT NULL, + `available` integer NOT NULL ); --> statement-breakpoint -CREATE TABLE `TournamentSettings` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `gamemode` integer DEFAULT 0 NOT NULL, - `force_nf` numeric NOT NULL, - `score_mode` integer NOT NULL, - `team_mode` integer NOT NULL, - `team_size` integer NOT NULL, - `x_v_x_mode` integer NOT NULL, - `fm_mods` integer DEFAULT 1 NOT NULL, - `double_pick` integer DEFAULT 1 NOT NULL, - `double_ban` integer DEFAULT 1 NOT NULL, - `tournament_id` integer, - `match_id` integer, - FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE set null +CREATE TABLE `MapInPool` ( + `identifier` text NOT NULL, + `map_order` integer, + `mods` text NOT NULL, + `mappool_id` integer NOT NULL, + `map_id` integer, + `tournamentSettingsId` integer, + PRIMARY KEY(`identifier`, `mappool_id`), + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`map_id`) REFERENCES `Map`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`tournamentSettingsId`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE set null ); --> statement-breakpoint -CREATE TABLE `ModMultiplier` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `mod_string` text NOT NULL, - `match_exactly` numeric DEFAULT false NOT NULL, - `multiplier` real NOT NULL +CREATE TABLE `MapStats` ( + `map_id` integer NOT NULL, + `mod_string` text DEFAULT '' NOT NULL, + `star_rating` real NOT NULL, + `bpm` real NOT NULL, + `length` integer NOT NULL, + `cs` real NOT NULL, + `ar` real NOT NULL, + `od` real NOT NULL, + `hp` real NOT NULL, + PRIMARY KEY(`map_id`, `mod_string`), + FOREIGN KEY (`map_id`) REFERENCES `Map`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `Round` ( +CREATE TABLE `Mappool` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `acronym` text NOT NULL, `name` text NOT NULL, - `tournament_id` integer NOT NULL, - FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade + `public` integer DEFAULT true NOT NULL ); --> statement-breakpoint CREATE TABLE `MappoolInRound` ( `mappool_id` integer NOT NULL, `round_id` integer NOT NULL, PRIMARY KEY(`mappool_id`, `round_id`), - FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE restrict, - FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE restrict + FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE restrict, + FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE restrict ); --> statement-breakpoint -CREATE TABLE `Mappool` ( +CREATE TABLE `Match` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `name` text NOT NULL, - `public` numeric DEFAULT false NOT NULL + `start_time` integer, + `mp_link` text, + `scrim` integer DEFAULT false NOT NULL, + `current_section_id` integer NOT NULL, + `block_in_section_id` integer NOT NULL, + `round_id` integer, + `settings_id` integer, + FOREIGN KEY (`current_section_id`) REFERENCES `BlockSection`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`block_in_section_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`settings_id`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE restrict ); --> statement-breakpoint -CREATE TABLE `MapInPool` ( - `identifier` text NOT NULL, - `mods` text NOT NULL, - `map_id` integer, - `map_order` integer, - `mappool_id` integer NOT NULL, - `tournamentSettingsId` integer, - PRIMARY KEY(`identifier`, `mappool_id`), - FOREIGN KEY (`tournamentSettingsId`) REFERENCES `TournamentSettings`(`id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE cascade, - FOREIGN KEY (`map_id`) REFERENCES `Map`(`id`) ON UPDATE cascade ON DELETE set null +CREATE TABLE `MatchBlock` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `section_id` integer NOT NULL, + `action` text NOT NULL, + `order_number` integer NOT NULL, + `map_identifier` text, + `pool_id` integer, + `acted_on_by_id` integer, + FOREIGN KEY (`section_id`) REFERENCES `BlockSection`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`action`) REFERENCES `BlockSection`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`map_identifier`) REFERENCES `MapInPool`(`identifier`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`pool_id`) REFERENCES `MapInPool`(`mappool_id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`acted_on_by_id`) REFERENCES `TeamInMatch`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `Map` ( +CREATE TABLE `ModMultiplier` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `beatmapset_id` integer NOT NULL, - `title` text NOT NULL, - `artist` text NOT NULL, - `difficulty_name` text NOT NULL, - `url` text NOT NULL, - `cover_url` text NOT NULL, - `status` text NOT NULL, - `total_length` integer NOT NULL, - `max_combo` integer NOT NULL, - `bpm` real NOT NULL, - `last_updated` numeric NOT NULL, - `cs` real NOT NULL, - `ar` real NOT NULL, - `od` real NOT NULL, - `hp` real NOT NULL, - `star_rating` real NOT NULL, - `star_rating_dt` real, - `star_rating_hr` real, - `star_rating_ez` real, - `star_rating_ht` real, - `available` numeric NOT NULL, - `fetch_time` numeric DEFAULT (CURRENT_TIMESTAMP) NOT NULL + `settings_id` integer, + `multiplier` real NOT NULL, + `mod_string` text NOT NULL, + `match_exactly` integer NOT NULL, + FOREIGN KEY (`settings_id`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint CREATE TABLE `OsuOauth` ( - `user_id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `last_update` numeric DEFAULT (CURRENT_TIMESTAMP) NOT NULL, + `user_id` integer PRIMARY KEY NOT NULL, + `token_type` text NOT NULL, `access_token` text NOT NULL, - `expires_in` integer NOT NULL, `refresh_token` text NOT NULL, - `token_type` text NOT NULL, - FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict -); ---> statement-breakpoint -CREATE TABLE `User` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `username` text NOT NULL, - `country_code` text NOT NULL, - `country_name` text NOT NULL, - `cover_url` text NOT NULL, - `ranked_score` integer NOT NULL, - `play_count` integer NOT NULL, - `total_score` integer NOT NULL, - `pp_rank` integer NOT NULL, - `level` integer NOT NULL, - `level_progress` integer NOT NULL, - `hit_accuracy` real NOT NULL, - `pp` real NOT NULL -); ---> statement-breakpoint -CREATE TABLE `UserInTeam` ( - `osu_id` integer NOT NULL, - `team_id` integer NOT NULL, - `member_order` integer DEFAULT 0 NOT NULL, - PRIMARY KEY(`osu_id`, `team_id`), - FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade, - FOREIGN KEY (`osu_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict + `expires_at` integer NOT NULL, + FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `Team` ( +CREATE TABLE `Round` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `acronym` text NOT NULL, `name` text NOT NULL, - `icon_url` text NOT NULL, - `color` text NOT NULL, `tournament_id` integer NOT NULL, - `timezone` integer, FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `TeamInvite` ( - `invitee_user_id` integer NOT NULL, - `team_id` integer NOT NULL, - PRIMARY KEY(`invitee_user_id`, `team_id`), - FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade, - FOREIGN KEY (`invitee_user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict -); ---> statement-breakpoint -CREATE TABLE `Match` ( +CREATE TABLE `Score` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `start_time` numeric, - `mp_link` text, - `round_id` integer, - `waiting_on` integer, - `current_section` integer NOT NULL, - `block_in_section` integer NOT NULL, - `scrim` numeric DEFAULT false NOT NULL, - FOREIGN KEY (`round_id`) REFERENCES `Round`(`id`) ON UPDATE cascade ON DELETE set null + `score` real NOT NULL, + `mods` text, + `block_id` integer NOT NULL, + `user_id` integer NOT NULL, + `team_score_id` integer, + FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`team_score_id`) REFERENCES `TeamScore`(`id`) ON UPDATE cascade ON DELETE set null ); --> statement-breakpoint -CREATE TABLE `BlockSection` ( +CREATE TABLE `Settings` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `match_id` integer NOT NULL, - `action` text NOT NULL, - FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE restrict + `gamemode` integer DEFAULT 0 NOT NULL, + `team_mode` integer NOT NULL, + `score_mode` integer NOT NULL, + `force_nf` integer DEFAULT true NOT NULL, + `fm_mods` integer DEFAULT 1 NOT NULL, + `player_count` integer NOT NULL, + `tournament_id` integer, + `match_id` integer, + FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE set null, + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE set null ); --> statement-breakpoint -CREATE TABLE `MatchBlock` ( +CREATE TABLE `Team` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `section_id` integer NOT NULL, - `action` text NOT NULL, - `map_identifier` text, - `pool_id` integer, - `acted_on_by_id` integer NOT NULL, - FOREIGN KEY (`acted_on_by_id`) REFERENCES `TeamInMatch`(`id`) ON UPDATE cascade ON DELETE restrict, - FOREIGN KEY (`map_identifier`,`pool_id`) REFERENCES `MapInPool`(`identifier`,`mappool_id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`section_id`,`action`) REFERENCES `BlockSection`(`id`,`action`) ON UPDATE cascade ON DELETE restrict + `name` text NOT NULL, + `icon_url` text, + `color` text NOT NULL, + `timezone` integer ); --> statement-breakpoint CREATE TABLE `TeamInMatch` ( @@ -199,62 +159,71 @@ CREATE TABLE `TeamInMatch` ( `team_id` integer, `score` integer NOT NULL, `roll` integer, + `winner` integer, `aborts` integer DEFAULT 0 NOT NULL, `faults` integer DEFAULT 0 NOT NULL, - `winner` numeric, - FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE cascade + FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE set null ); --> statement-breakpoint -CREATE TABLE `Score` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `score` real NOT NULL, - `mods` text DEFAULT '' NOT NULL, - `block_id` integer NOT NULL, - `user_id` integer NOT NULL, - `team_score_id` integer, - FOREIGN KEY (`team_score_id`) REFERENCES `TeamScore`(`id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE restrict, - FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE restrict +CREATE TABLE `TeamInTournament` ( + `id` integer, + PRIMARY KEY(`id`, `id`), + FOREIGN KEY (`id`) REFERENCES `Tournament`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`id`) REFERENCES `Team`(`id`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint CREATE TABLE `TeamScore` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `score` real NOT NULL, - `freemod` numeric DEFAULT false NOT NULL, `block_id` integer NOT NULL, `team_id` integer NOT NULL, - FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE restrict, - FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE restrict + FOREIGN KEY (`block_id`) REFERENCES `MatchBlock`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `MappoolInMatch` ( - `mappool_id` integer NOT NULL, - `match_id` integer NOT NULL, - PRIMARY KEY(`mappool_id`, `match_id`), - FOREIGN KEY (`match_id`) REFERENCES `Match`(`id`) ON UPDATE cascade ON DELETE restrict, - FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE restrict +CREATE TABLE `Tournament` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text NOT NULL, + `acronym` text NOT NULL, + `settings_id` integer, + `allow_registrations` integer DEFAULT true NOT NULL, + `private` integer NOT NULL, + `team_size` integer NOT NULL, + `color` text, + `banner_url` text, + `description` text, + `icon_url` text, + FOREIGN KEY (`settings_id`) REFERENCES `Settings`(`id`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint -CREATE TABLE `_TournamentToUser` ( - `A` integer NOT NULL, - `B` integer NOT NULL, - FOREIGN KEY (`B`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade, - FOREIGN KEY (`A`) REFERENCES `Tournament`(`id`) ON UPDATE cascade ON DELETE cascade +CREATE TABLE `User` ( + `id` integer PRIMARY KEY NOT NULL, + `username` text NOT NULL, + `country_code` text NOT NULL, + `country_name` text NOT NULL, + `cover_url` text NOT NULL, + `avatar_url` text NOT NULL, + `pp` real, + `global_rank` integer, + `country_rank` integer, + `total_score` integer, + `ranked_score` integer, + `hit_accuracy` real, + `play_count` integer, + `level` integer, + `level_progress` integer ); --> statement-breakpoint -CREATE TABLE `_ModMultiplierToSettings` ( - `A` integer NOT NULL, - `B` integer NOT NULL, - FOREIGN KEY (`B`) REFERENCES `TournamentSettings`(`id`) ON UPDATE cascade ON DELETE cascade, - FOREIGN KEY (`A`) REFERENCES `ModMultiplier`(`id`) ON UPDATE cascade ON DELETE cascade +CREATE TABLE `UserInTeam` ( + `user_id` integer NOT NULL, + `team_id` integer NOT NULL, + `invite` integer, + `member_order` integer DEFAULT 0, + PRIMARY KEY(`team_id`, `user_id`), + FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE UNIQUE INDEX `TournamentSettings_match_id_key` ON `TournamentSettings` (`match_id`);--> statement-breakpoint -CREATE UNIQUE INDEX `TournamentSettings_tournament_id_key` ON `TournamentSettings` (`tournament_id`);--> statement-breakpoint -CREATE UNIQUE INDEX `BlockSection_id_action_key` ON `BlockSection` (`id`,`action`);--> statement-breakpoint -CREATE INDEX `_TournamentToUser_B_index` ON `_TournamentToUser` (`B`);--> statement-breakpoint -CREATE UNIQUE INDEX `_TournamentToUser_AB_unique` ON `_TournamentToUser` (`A`,`B`);--> statement-breakpoint -CREATE INDEX `_ModMultiplierToSettings_B_index` ON `_ModMultiplierToSettings` (`B`);--> statement-breakpoint -CREATE UNIQUE INDEX `_ModMultiplierToSettings_AB_unique` ON `_ModMultiplierToSettings` (`A`,`B`); -*/ \ No newline at end of file +CREATE UNIQUE INDEX `Settings_tournament_id_unique` ON `Settings` (`tournament_id`);--> statement-breakpoint +CREATE UNIQUE INDEX `Settings_match_id_unique` ON `Settings` (`match_id`); \ No newline at end of file diff --git a/src/lib/drizzle/meta/0000_snapshot.json b/src/lib/drizzle/meta/0000_snapshot.json index 2b0d582..d263ac6 100644 --- a/src/lib/drizzle/meta/0000_snapshot.json +++ b/src/lib/drizzle/meta/0000_snapshot.json @@ -1,266 +1,234 @@ { - "id": "00000000-0000-0000-0000-000000000000", - "prevId": "", "version": "6", "dialect": "sqlite", + "id": "ef9eedf8-f8b9-42e6-a743-12e6f3c63358", + "prevId": "00000000-0000-0000-0000-000000000000", "tables": { - "_prisma_migrations": { - "name": "_prisma_migrations", + "BlockSection": { + "name": "BlockSection", "columns": { "id": { - "autoincrement": false, "name": "id", - "type": "text", + "type": "integer", "primaryKey": true, - "notNull": true - }, - "checksum": { - "autoincrement": false, - "name": "checksum", - "type": "text", - "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": true }, - "finished_at": { - "autoincrement": false, - "name": "finished_at", - "type": "numeric", + "match_id": { + "name": "match_id", + "type": "integer", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "migration_name": { - "autoincrement": false, - "name": "migration_name", - "type": "text", + "mappool_id": { + "name": "mappool_id", + "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "logs": { - "autoincrement": false, - "name": "logs", + "action": { + "name": "action", "type": "text", "primaryKey": false, - "notNull": false - }, - "rolled_back_at": { - "autoincrement": false, - "name": "rolled_back_at", - "type": "numeric", - "primaryKey": false, - "notNull": false - }, - "started_at": { - "default": "(current_timestamp)", - "autoincrement": false, - "name": "started_at", - "type": "numeric", - "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "BlockSection_match_id_Match_id_fk": { + "name": "BlockSection_match_id_Match_id_fk", + "tableFrom": "BlockSection", + "tableTo": "Match", + "columnsFrom": [ + "match_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" }, - "applied_steps_count": { - "default": 0, - "autoincrement": false, - "name": "applied_steps_count", - "type": "integer", - "primaryKey": false, - "notNull": true + "BlockSection_mappool_id_Mappool_id_fk": { + "name": "BlockSection_mappool_id_Mappool_id_fk", + "tableFrom": "BlockSection", + "tableTo": "Mappool", + "columnsFrom": [ + "mappool_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, - "indexes": {}, - "foreignKeys": {}, "uniqueConstraints": {} }, - "Tournament": { - "name": "Tournament", + "Map": { + "name": "Map", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true - }, - "name": { - "autoincrement": false, - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "acronym": { - "autoincrement": false, - "name": "acronym", - "type": "text", + "beatmapset_id": { + "name": "beatmapset_id", + "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "allow_registrations": { - "default": true, - "autoincrement": false, - "name": "allow_registrations", - "type": "numeric", + "fetch_time": { + "name": "fetch_time", + "type": "integer", "primaryKey": false, - "notNull": true - }, - "private": { - "default": false, + "notNull": true, "autoincrement": false, - "name": "private", - "type": "numeric", - "primaryKey": false, - "notNull": true + "default": "(CURRENT_TIMESTAMP)" }, - "color": { - "autoincrement": false, - "name": "color", + "title": { + "name": "title", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "banner_url": { - "autoincrement": false, - "name": "banner_url", + "artist": { + "name": "artist", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "description": { - "autoincrement": false, - "name": "description", + "difficulty_name": { + "name": "difficulty_name", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "icon_url": { - "autoincrement": false, - "name": "icon_url", + "url": { + "name": "url", "type": "text", "primaryKey": false, - "notNull": false - } - }, - "compositePrimaryKeys": {}, - "indexes": {}, - "foreignKeys": {}, - "uniqueConstraints": {} - }, - "TournamentSettings": { - "name": "TournamentSettings", - "columns": { - "id": { - "autoincrement": true, - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": false }, - "gamemode": { - "default": 0, - "autoincrement": false, - "name": "gamemode", - "type": "integer", + "cover_url": { + "name": "cover_url", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "force_nf": { - "autoincrement": false, - "name": "force_nf", - "type": "numeric", + "status": { + "name": "status", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "score_mode": { - "autoincrement": false, - "name": "score_mode", + "max_combo": { + "name": "max_combo", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "team_mode": { - "autoincrement": false, - "name": "team_mode", + "last_updated": { + "name": "last_updated", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "team_size": { - "autoincrement": false, - "name": "team_size", + "available": { + "name": "available", "type": "integer", "primaryKey": false, - "notNull": true - }, - "x_v_x_mode": { - "autoincrement": false, - "name": "x_v_x_mode", - "type": "integer", + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "MapInPool": { + "name": "MapInPool", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "fm_mods": { - "default": 1, - "autoincrement": false, - "name": "fm_mods", + "map_order": { + "name": "map_order", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "double_pick": { - "default": 1, - "autoincrement": false, - "name": "double_pick", - "type": "integer", + "mods": { + "name": "mods", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "double_ban": { - "default": 1, - "autoincrement": false, - "name": "double_ban", + "mappool_id": { + "name": "mappool_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "tournament_id": { - "autoincrement": false, - "name": "tournament_id", + "map_id": { + "name": "map_id", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false }, - "match_id": { - "autoincrement": false, - "name": "match_id", + "tournamentSettingsId": { + "name": "tournamentSettingsId", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, - "indexes": { - "TournamentSettings_match_id_key": { - "name": "TournamentSettings_match_id_key", - "columns": [ - "match_id" + "indexes": {}, + "foreignKeys": { + "MapInPool_mappool_id_Mappool_id_fk": { + "name": "MapInPool_mappool_id_Mappool_id_fk", + "tableFrom": "MapInPool", + "tableTo": "Mappool", + "columnsFrom": [ + "mappool_id" ], - "isUnique": true - }, - "TournamentSettings_tournament_id_key": { - "name": "TournamentSettings_tournament_id_key", - "columns": [ - "tournament_id" + "columnsTo": [ + "id" ], - "isUnique": true - } - }, - "foreignKeys": { - "TournamentSettings_match_id_Match_id_fk": { - "name": "TournamentSettings_match_id_Match_id_fk", - "tableFrom": "TournamentSettings", - "tableTo": "Match", + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "MapInPool_map_id_Map_id_fk": { + "name": "MapInPool_map_id_Map_id_fk", + "tableFrom": "MapInPool", + "tableTo": "Map", "columnsFrom": [ - "match_id" + "map_id" ], "columnsTo": [ "id" @@ -268,12 +236,12 @@ "onDelete": "set null", "onUpdate": "cascade" }, - "TournamentSettings_tournament_id_Tournament_id_fk": { - "name": "TournamentSettings_tournament_id_Tournament_id_fk", - "tableFrom": "TournamentSettings", - "tableTo": "Tournament", + "MapInPool_tournamentSettingsId_Settings_id_fk": { + "name": "MapInPool_tournamentSettingsId_Settings_id_fk", + "tableFrom": "MapInPool", + "tableTo": "Settings", "columnsFrom": [ - "tournament_id" + "tournamentSettingsId" ], "columnsTo": [ "id" @@ -282,87 +250,93 @@ "onUpdate": "cascade" } }, + "compositePrimaryKeys": { + "MapInPool_identifier_mappool_id_pk": { + "columns": [ + "identifier", + "mappool_id" + ], + "name": "MapInPool_identifier_mappool_id_pk" + } + }, "uniqueConstraints": {} }, - "ModMultiplier": { - "name": "ModMultiplier", + "MapStats": { + "name": "MapStats", "columns": { - "id": { - "autoincrement": true, - "name": "id", + "map_id": { + "name": "map_id", "type": "integer", - "primaryKey": true, - "notNull": true + "primaryKey": false, + "notNull": true, + "autoincrement": false }, "mod_string": { - "autoincrement": false, "name": "mod_string", "type": "text", "primaryKey": false, - "notNull": true - }, - "match_exactly": { - "default": false, + "notNull": true, "autoincrement": false, - "name": "match_exactly", - "type": "numeric", + "default": "''" + }, + "star_rating": { + "name": "star_rating", + "type": "real", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "multiplier": { - "autoincrement": false, - "name": "multiplier", + "bpm": { + "name": "bpm", "type": "real", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": {}, - "indexes": {}, - "foreignKeys": {}, - "uniqueConstraints": {} - }, - "Round": { - "name": "Round", - "columns": { - "id": { - "autoincrement": true, - "name": "id", + "notNull": true, + "autoincrement": false + }, + "length": { + "name": "length", "type": "integer", - "primaryKey": true, - "notNull": true + "primaryKey": false, + "notNull": true, + "autoincrement": false }, - "acronym": { - "autoincrement": false, - "name": "acronym", - "type": "text", + "cs": { + "name": "cs", + "type": "real", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "name": { - "autoincrement": false, - "name": "name", - "type": "text", + "ar": { + "name": "ar", + "type": "real", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "tournament_id": { - "autoincrement": false, - "name": "tournament_id", - "type": "integer", + "od": { + "name": "od", + "type": "real", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false + }, + "hp": { + "name": "hp", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "Round_tournament_id_Tournament_id_fk": { - "name": "Round_tournament_id_Tournament_id_fk", - "tableFrom": "Round", - "tableTo": "Tournament", + "MapStats_map_id_Map_id_fk": { + "name": "MapStats_map_id_Map_id_fk", + "tableFrom": "MapStats", + "tableTo": "Map", "columnsFrom": [ - "tournament_id" + "map_id" ], "columnsTo": [ "id" @@ -371,62 +345,13 @@ "onUpdate": "cascade" } }, - "uniqueConstraints": {} - }, - "MappoolInRound": { - "name": "MappoolInRound", - "columns": { - "mappool_id": { - "autoincrement": false, - "name": "mappool_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "round_id": { - "autoincrement": false, - "name": "round_id", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, "compositePrimaryKeys": { - "MappoolInRound_mappool_id_round_id_pk": { + "MapStats_map_id_mod_string_pk": { "columns": [ - "mappool_id", - "round_id" + "map_id", + "mod_string" ], - "name": "MappoolInRound_mappool_id_round_id_pk" - } - }, - "indexes": {}, - "foreignKeys": { - "MappoolInRound_round_id_Round_id_fk": { - "name": "MappoolInRound_round_id_Round_id_fk", - "tableFrom": "MappoolInRound", - "tableTo": "Round", - "columnsFrom": [ - "round_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "MappoolInRound_mappool_id_Mappool_id_fk": { - "name": "MappoolInRound_mappool_id_Mappool_id_fk", - "tableFrom": "MappoolInRound", - "tableTo": "Mappool", - "columnsFrom": [ - "mappool_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" + "name": "MapStats_map_id_mod_string_pk" } }, "uniqueConstraints": {} @@ -435,106 +360,56 @@ "name": "Mappool", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, "name": { - "autoincrement": false, "name": "name", "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, "public": { - "default": false, - "autoincrement": false, "name": "public", - "type": "numeric", + "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false, + "default": true } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": {}, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "MapInPool": { - "name": "MapInPool", + "MappoolInRound": { + "name": "MappoolInRound", "columns": { - "identifier": { - "autoincrement": false, - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "mods": { - "autoincrement": false, - "name": "mods", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "map_id": { - "autoincrement": false, - "name": "map_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "map_order": { - "autoincrement": false, - "name": "map_order", - "type": "integer", - "primaryKey": false, - "notNull": false - }, "mappool_id": { - "autoincrement": false, "name": "mappool_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "tournamentSettingsId": { - "autoincrement": false, - "name": "tournamentSettingsId", + "round_id": { + "name": "round_id", "type": "integer", "primaryKey": false, - "notNull": false - } - }, - "compositePrimaryKeys": { - "MapInPool_identifier_mappool_id_pk": { - "columns": [ - "identifier", - "mappool_id" - ], - "name": "MapInPool_identifier_mappool_id_pk" + "notNull": true, + "autoincrement": false } }, "indexes": {}, "foreignKeys": { - "MapInPool_tournamentSettingsId_TournamentSettings_id_fk": { - "name": "MapInPool_tournamentSettingsId_TournamentSettings_id_fk", - "tableFrom": "MapInPool", - "tableTo": "TournamentSettings", - "columnsFrom": [ - "tournamentSettingsId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "set null", - "onUpdate": "cascade" - }, - "MapInPool_mappool_id_Mappool_id_fk": { - "name": "MapInPool_mappool_id_Mappool_id_fk", - "tableFrom": "MapInPool", + "MappoolInRound_mappool_id_Mappool_id_fk": { + "name": "MappoolInRound_mappool_id_Mappool_id_fk", + "tableFrom": "MappoolInRound", "tableTo": "Mappool", "columnsFrom": [ "mappool_id" @@ -542,483 +417,324 @@ "columnsTo": [ "id" ], - "onDelete": "cascade", + "onDelete": "restrict", "onUpdate": "cascade" }, - "MapInPool_map_id_Map_id_fk": { - "name": "MapInPool_map_id_Map_id_fk", - "tableFrom": "MapInPool", - "tableTo": "Map", + "MappoolInRound_round_id_Round_id_fk": { + "name": "MappoolInRound_round_id_Round_id_fk", + "tableFrom": "MappoolInRound", + "tableTo": "Round", "columnsFrom": [ - "map_id" + "round_id" ], "columnsTo": [ "id" ], - "onDelete": "set null", + "onDelete": "restrict", "onUpdate": "cascade" } }, + "compositePrimaryKeys": { + "MappoolInRound_mappool_id_round_id_pk": { + "columns": [ + "mappool_id", + "round_id" + ], + "name": "MappoolInRound_mappool_id_round_id_pk" + } + }, "uniqueConstraints": {} }, - "Map": { - "name": "Map", + "Match": { + "name": "Match", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, - "beatmapset_id": { - "autoincrement": false, - "name": "beatmapset_id", + "start_time": { + "name": "start_time", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "title": { - "autoincrement": false, - "name": "title", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "artist": { - "autoincrement": false, - "name": "artist", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "difficulty_name": { - "autoincrement": false, - "name": "difficulty_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "url": { - "autoincrement": false, - "name": "url", + "mp_link": { + "name": "mp_link", "type": "text", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "cover_url": { - "autoincrement": false, - "name": "cover_url", - "type": "text", + "scrim": { + "name": "scrim", + "type": "integer", "primaryKey": false, - "notNull": true - }, - "status": { + "notNull": true, "autoincrement": false, - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true + "default": false }, - "total_length": { - "autoincrement": false, - "name": "total_length", + "current_section_id": { + "name": "current_section_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "max_combo": { - "autoincrement": false, - "name": "max_combo", + "block_in_section_id": { + "name": "block_in_section_id", "type": "integer", "primaryKey": false, - "notNull": true - }, - "bpm": { - "autoincrement": false, - "name": "bpm", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "last_updated": { - "autoincrement": false, - "name": "last_updated", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "cs": { - "autoincrement": false, - "name": "cs", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "ar": { - "autoincrement": false, - "name": "ar", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "od": { - "autoincrement": false, - "name": "od", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "hp": { - "autoincrement": false, - "name": "hp", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "star_rating": { - "autoincrement": false, - "name": "star_rating", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "star_rating_dt": { - "autoincrement": false, - "name": "star_rating_dt", - "type": "real", - "primaryKey": false, - "notNull": false - }, - "star_rating_hr": { - "autoincrement": false, - "name": "star_rating_hr", - "type": "real", - "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "star_rating_ez": { - "autoincrement": false, - "name": "star_rating_ez", - "type": "real", - "primaryKey": false, - "notNull": false - }, - "star_rating_ht": { - "autoincrement": false, - "name": "star_rating_ht", - "type": "real", - "primaryKey": false, - "notNull": false - }, - "available": { - "autoincrement": false, - "name": "available", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "fetch_time": { - "default": "(CURRENT_TIMESTAMP)", - "autoincrement": false, - "name": "fetch_time", - "type": "numeric", - "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": {}, - "indexes": {}, - "foreignKeys": {}, - "uniqueConstraints": {} - }, - "OsuOauth": { - "name": "OsuOauth", - "columns": { - "user_id": { - "autoincrement": true, - "name": "user_id", + "round_id": { + "name": "round_id", "type": "integer", - "primaryKey": true, - "notNull": true - }, - "last_update": { - "default": "(CURRENT_TIMESTAMP)", - "autoincrement": false, - "name": "last_update", - "type": "numeric", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "autoincrement": false, - "name": "access_token", - "type": "text", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "expires_in": { - "autoincrement": false, - "name": "expires_in", + "settings_id": { + "name": "settings_id", "type": "integer", "primaryKey": false, - "notNull": true - }, - "refresh_token": { - "autoincrement": false, - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "token_type": { - "autoincrement": false, - "name": "token_type", - "type": "text", - "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "OsuOauth_user_id_User_id_fk": { - "name": "OsuOauth_user_id_User_id_fk", - "tableFrom": "OsuOauth", - "tableTo": "User", + "Match_current_section_id_BlockSection_id_fk": { + "name": "Match_current_section_id_BlockSection_id_fk", + "tableFrom": "Match", + "tableTo": "BlockSection", "columnsFrom": [ - "user_id" + "current_section_id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "uniqueConstraints": {} - }, - "User": { - "name": "User", - "columns": { - "id": { - "autoincrement": true, - "name": "id", - "type": "integer", - "primaryKey": true, - "notNull": true - }, - "username": { - "autoincrement": false, - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "country_code": { - "autoincrement": false, - "name": "country_code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "country_name": { - "autoincrement": false, - "name": "country_name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "cover_url": { - "autoincrement": false, - "name": "cover_url", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "ranked_score": { - "autoincrement": false, - "name": "ranked_score", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "play_count": { - "autoincrement": false, - "name": "play_count", - "type": "integer", - "primaryKey": false, - "notNull": true + "onDelete": "no action", + "onUpdate": "no action" }, - "total_score": { - "autoincrement": false, - "name": "total_score", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "pp_rank": { - "autoincrement": false, - "name": "pp_rank", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "level": { - "autoincrement": false, - "name": "level", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "level_progress": { - "autoincrement": false, - "name": "level_progress", - "type": "integer", - "primaryKey": false, - "notNull": true + "Match_block_in_section_id_MatchBlock_id_fk": { + "name": "Match_block_in_section_id_MatchBlock_id_fk", + "tableFrom": "Match", + "tableTo": "MatchBlock", + "columnsFrom": [ + "block_in_section_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" }, - "hit_accuracy": { - "autoincrement": false, - "name": "hit_accuracy", - "type": "real", - "primaryKey": false, - "notNull": true + "Match_round_id_Round_id_fk": { + "name": "Match_round_id_Round_id_fk", + "tableFrom": "Match", + "tableTo": "Round", + "columnsFrom": [ + "round_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" }, - "pp": { - "autoincrement": false, - "name": "pp", - "type": "real", - "primaryKey": false, - "notNull": true + "Match_settings_id_Settings_id_fk": { + "name": "Match_settings_id_Settings_id_fk", + "tableFrom": "Match", + "tableTo": "Settings", + "columnsFrom": [ + "settings_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" } }, "compositePrimaryKeys": {}, - "indexes": {}, - "foreignKeys": {}, "uniqueConstraints": {} }, - "UserInTeam": { - "name": "UserInTeam", + "MatchBlock": { + "name": "MatchBlock", "columns": { - "osu_id": { - "autoincrement": false, - "name": "osu_id", + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "section_id": { + "name": "section_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "team_id": { - "autoincrement": false, - "name": "team_id", + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "order_number": { + "name": "order_number", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "member_order": { - "default": 0, - "autoincrement": false, - "name": "member_order", + "map_identifier": { + "name": "map_identifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pool_id": { + "name": "pool_id", "type": "integer", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": { - "UserInTeam_osu_id_team_id_pk": { - "columns": [ - "osu_id", - "team_id" - ], - "name": "UserInTeam_osu_id_team_id_pk" + "notNull": false, + "autoincrement": false + }, + "acted_on_by_id": { + "name": "acted_on_by_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, "indexes": {}, "foreignKeys": { - "UserInTeam_team_id_Team_id_fk": { - "name": "UserInTeam_team_id_Team_id_fk", - "tableFrom": "UserInTeam", - "tableTo": "Team", + "MatchBlock_section_id_BlockSection_id_fk": { + "name": "MatchBlock_section_id_BlockSection_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "BlockSection", "columnsFrom": [ - "team_id" + "section_id" ], "columnsTo": [ "id" ], - "onDelete": "cascade", - "onUpdate": "cascade" + "onDelete": "no action", + "onUpdate": "no action" }, - "UserInTeam_osu_id_User_id_fk": { - "name": "UserInTeam_osu_id_User_id_fk", - "tableFrom": "UserInTeam", - "tableTo": "User", + "MatchBlock_action_BlockSection_id_fk": { + "name": "MatchBlock_action_BlockSection_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "BlockSection", "columnsFrom": [ - "osu_id" + "action" ], "columnsTo": [ "id" ], - "onDelete": "restrict", + "onDelete": "no action", + "onUpdate": "no action" + }, + "MatchBlock_map_identifier_MapInPool_identifier_fk": { + "name": "MatchBlock_map_identifier_MapInPool_identifier_fk", + "tableFrom": "MatchBlock", + "tableTo": "MapInPool", + "columnsFrom": [ + "map_identifier" + ], + "columnsTo": [ + "identifier" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "MatchBlock_pool_id_MapInPool_mappool_id_fk": { + "name": "MatchBlock_pool_id_MapInPool_mappool_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "MapInPool", + "columnsFrom": [ + "pool_id" + ], + "columnsTo": [ + "mappool_id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "MatchBlock_acted_on_by_id_TeamInMatch_id_fk": { + "name": "MatchBlock_acted_on_by_id_TeamInMatch_id_fk", + "tableFrom": "MatchBlock", + "tableTo": "TeamInMatch", + "columnsFrom": [ + "acted_on_by_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "Team": { - "name": "Team", + "ModMultiplier": { + "name": "ModMultiplier", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, - "name": { - "autoincrement": false, - "name": "name", - "type": "text", + "settings_id": { + "name": "settings_id", + "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "icon_url": { - "autoincrement": false, - "name": "icon_url", - "type": "text", + "multiplier": { + "name": "multiplier", + "type": "real", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "color": { - "autoincrement": false, - "name": "color", + "mod_string": { + "name": "mod_string", "type": "text", "primaryKey": false, - "notNull": true - }, - "tournament_id": { - "autoincrement": false, - "name": "tournament_id", - "type": "integer", - "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "timezone": { - "autoincrement": false, - "name": "timezone", + "match_exactly": { + "name": "match_exactly", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "Team_tournament_id_Tournament_id_fk": { - "name": "Team_tournament_id_Tournament_id_fk", - "tableFrom": "Team", - "tableTo": "Tournament", + "ModMultiplier_settings_id_Settings_id_fk": { + "name": "ModMultiplier_settings_id_Settings_id_fk", + "tableFrom": "ModMultiplier", + "tableTo": "Settings", "columnsFrom": [ - "tournament_id" + "settings_id" ], "columnsTo": [ "id" @@ -1027,136 +743,198 @@ "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "TeamInvite": { - "name": "TeamInvite", + "OsuOauth": { + "name": "OsuOauth", "columns": { - "invitee_user_id": { - "autoincrement": false, - "name": "invitee_user_id", + "user_id": { + "name": "user_id", "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "token_type": { + "name": "token_type", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "team_id": { - "autoincrement": false, - "name": "team_id", + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", "type": "integer", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": { - "TeamInvite_invitee_user_id_team_id_pk": { - "columns": [ - "invitee_user_id", - "team_id" - ], - "name": "TeamInvite_invitee_user_id_team_id_pk" + "notNull": true, + "autoincrement": false } }, "indexes": {}, "foreignKeys": { - "TeamInvite_team_id_Team_id_fk": { - "name": "TeamInvite_team_id_Team_id_fk", - "tableFrom": "TeamInvite", - "tableTo": "Team", + "OsuOauth_user_id_User_id_fk": { + "name": "OsuOauth_user_id_User_id_fk", + "tableFrom": "OsuOauth", + "tableTo": "User", "columnsFrom": [ - "team_id" + "user_id" ], "columnsTo": [ "id" ], "onDelete": "cascade", "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "Round": { + "name": "Round", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true }, - "TeamInvite_invitee_user_id_User_id_fk": { - "name": "TeamInvite_invitee_user_id_User_id_fk", - "tableFrom": "TeamInvite", - "tableTo": "User", + "acronym": { + "name": "acronym", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tournament_id": { + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "Round_tournament_id_Tournament_id_fk": { + "name": "Round_tournament_id_Tournament_id_fk", + "tableFrom": "Round", + "tableTo": "Tournament", "columnsFrom": [ - "invitee_user_id" + "tournament_id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", + "onDelete": "cascade", "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "Match": { - "name": "Match", + "Score": { + "name": "Score", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, - "start_time": { - "autoincrement": false, - "name": "start_time", - "type": "numeric", + "score": { + "name": "score", + "type": "real", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "mp_link": { - "autoincrement": false, - "name": "mp_link", + "mods": { + "name": "mods", "type": "text", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false }, - "round_id": { - "autoincrement": false, - "name": "round_id", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "waiting_on": { - "autoincrement": false, - "name": "waiting_on", + "block_id": { + "name": "block_id", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "current_section": { - "autoincrement": false, - "name": "current_section", + "user_id": { + "name": "user_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "block_in_section": { - "autoincrement": false, - "name": "block_in_section", + "team_score_id": { + "name": "team_score_id", "type": "integer", "primaryKey": false, - "notNull": true - }, - "scrim": { - "default": false, - "autoincrement": false, - "name": "scrim", - "type": "numeric", - "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "Match_round_id_Round_id_fk": { - "name": "Match_round_id_Round_id_fk", - "tableFrom": "Match", - "tableTo": "Round", + "Score_block_id_MatchBlock_id_fk": { + "name": "Score_block_id_MatchBlock_id_fk", + "tableFrom": "Score", + "tableTo": "MatchBlock", + "columnsFrom": [ + "block_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Score_user_id_User_id_fk": { + "name": "Score_user_id_User_id_fk", + "tableFrom": "Score", + "tableTo": "User", "columnsFrom": [ - "round_id" + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "Score_team_score_id_TeamScore_id_fk": { + "name": "Score_team_score_id_TeamScore_id_fk", + "tableFrom": "Score", + "tableTo": "TeamScore", + "columnsFrom": [ + "team_score_id" ], "columnsTo": [ "id" @@ -1165,48 +943,112 @@ "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "BlockSection": { - "name": "BlockSection", + "Settings": { + "name": "Settings", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, - "match_id": { + "gamemode": { + "name": "gamemode", + "type": "integer", + "primaryKey": false, + "notNull": true, "autoincrement": false, - "name": "match_id", + "default": 0 + }, + "team_mode": { + "name": "team_mode", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "action": { + "score_mode": { + "name": "score_mode", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "force_nf": { + "name": "force_nf", + "type": "integer", + "primaryKey": false, + "notNull": true, "autoincrement": false, - "name": "action", - "type": "text", + "default": true + }, + "fm_mods": { + "name": "fm_mods", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "player_count": { + "name": "player_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tournament_id": { + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "match_id": { + "name": "match_id", + "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": { - "BlockSection_id_action_key": { - "name": "BlockSection_id_action_key", + "Settings_tournament_id_unique": { + "name": "Settings_tournament_id_unique", "columns": [ - "id", - "action" + "tournament_id" + ], + "isUnique": true + }, + "Settings_match_id_unique": { + "name": "Settings_match_id_unique", + "columns": [ + "match_id" ], "isUnique": true } }, "foreignKeys": { - "BlockSection_match_id_Match_id_fk": { - "name": "BlockSection_match_id_Match_id_fk", - "tableFrom": "BlockSection", + "Settings_tournament_id_Tournament_id_fk": { + "name": "Settings_tournament_id_Tournament_id_fk", + "tableFrom": "Settings", + "tableTo": "Tournament", + "columnsFrom": [ + "tournament_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "Settings_match_id_Match_id_fk": { + "name": "Settings_match_id_Match_id_fk", + "tableFrom": "Settings", "tableTo": "Match", "columnsFrom": [ "match_id" @@ -1214,289 +1056,198 @@ "columnsTo": [ "id" ], - "onDelete": "restrict", + "onDelete": "set null", "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "MatchBlock": { - "name": "MatchBlock", + "Team": { + "name": "Team", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, - "section_id": { - "autoincrement": false, - "name": "section_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "action": { - "autoincrement": false, - "name": "action", + "name": { + "name": "name", "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "map_identifier": { - "autoincrement": false, - "name": "map_identifier", + "icon_url": { + "name": "icon_url", "type": "text", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false }, - "pool_id": { - "autoincrement": false, - "name": "pool_id", - "type": "integer", + "color": { + "name": "color", + "type": "text", "primaryKey": false, - "notNull": false + "notNull": true, + "autoincrement": false }, - "acted_on_by_id": { - "autoincrement": false, - "name": "acted_on_by_id", + "timezone": { + "name": "timezone", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, - "foreignKeys": { - "MatchBlock_acted_on_by_id_TeamInMatch_id_fk": { - "name": "MatchBlock_acted_on_by_id_TeamInMatch_id_fk", - "tableFrom": "MatchBlock", - "tableTo": "TeamInMatch", - "columnsFrom": [ - "acted_on_by_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "MatchBlock_map_identifier_pool_id_MapInPool_identifier_mappool_id_fk": { - "name": "MatchBlock_map_identifier_pool_id_MapInPool_identifier_mappool_id_fk", - "tableFrom": "MatchBlock", - "tableTo": "MapInPool", - "columnsFrom": [ - "map_identifier", - "pool_id" - ], - "columnsTo": [ - "identifier", - "mappool_id" - ], - "onDelete": "set null", - "onUpdate": "cascade" - }, - "MatchBlock_section_id_action_BlockSection_id_action_fk": { - "name": "MatchBlock_section_id_action_BlockSection_id_action_fk", - "tableFrom": "MatchBlock", - "tableTo": "BlockSection", - "columnsFrom": [ - "section_id", - "action" - ], - "columnsTo": [ - "id", - "action" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, "TeamInMatch": { "name": "TeamInMatch", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, "match_id": { - "autoincrement": false, "name": "match_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, "team_id": { - "autoincrement": false, "name": "team_id", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false }, "score": { - "autoincrement": false, "name": "score", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, "roll": { - "autoincrement": false, "name": "roll", "type": "integer", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false + }, + "winner": { + "name": "winner", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false }, "aborts": { - "default": 0, - "autoincrement": false, "name": "aborts", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false, + "default": 0 }, "faults": { - "default": 0, - "autoincrement": false, "name": "faults", "type": "integer", "primaryKey": false, - "notNull": true - }, - "winner": { + "notNull": true, "autoincrement": false, - "name": "winner", - "type": "numeric", - "primaryKey": false, - "notNull": false + "default": 0 } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "TeamInMatch_team_id_Team_id_fk": { - "name": "TeamInMatch_team_id_Team_id_fk", + "TeamInMatch_match_id_Match_id_fk": { + "name": "TeamInMatch_match_id_Match_id_fk", "tableFrom": "TeamInMatch", - "tableTo": "Team", + "tableTo": "Match", "columnsFrom": [ - "team_id" + "match_id" ], "columnsTo": [ "id" ], - "onDelete": "set null", + "onDelete": "cascade", "onUpdate": "cascade" }, - "TeamInMatch_match_id_Match_id_fk": { - "name": "TeamInMatch_match_id_Match_id_fk", + "TeamInMatch_team_id_Team_id_fk": { + "name": "TeamInMatch_team_id_Team_id_fk", "tableFrom": "TeamInMatch", - "tableTo": "Match", + "tableTo": "Team", "columnsFrom": [ - "match_id" + "team_id" ], "columnsTo": [ "id" ], - "onDelete": "cascade", + "onDelete": "set null", "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "Score": { - "name": "Score", + "TeamInTournament": { + "name": "TeamInTournament", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", - "primaryKey": true, - "notNull": true - }, - "score": { - "autoincrement": false, - "name": "score", - "type": "real", - "primaryKey": false, - "notNull": true - }, - "mods": { - "default": "''", - "autoincrement": false, - "name": "mods", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "block_id": { - "autoincrement": false, - "name": "block_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "autoincrement": false, - "name": "user_id", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "team_score_id": { - "autoincrement": false, - "name": "team_score_id", - "type": "integer", "primaryKey": false, - "notNull": false + "notNull": false, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "Score_team_score_id_TeamScore_id_fk": { - "name": "Score_team_score_id_TeamScore_id_fk", - "tableFrom": "Score", - "tableTo": "TeamScore", + "TeamInTournament_id_Tournament_id_fk": { + "name": "TeamInTournament_id_Tournament_id_fk", + "tableFrom": "TeamInTournament", + "tableTo": "Tournament", "columnsFrom": [ - "team_score_id" - ], - "columnsTo": [ "id" ], - "onDelete": "set null", - "onUpdate": "cascade" - }, - "Score_user_id_User_id_fk": { - "name": "Score_user_id_User_id_fk", - "tableFrom": "Score", - "tableTo": "User", - "columnsFrom": [ - "user_id" - ], "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "Score_block_id_MatchBlock_id_fk": { - "name": "Score_block_id_MatchBlock_id_fk", - "tableFrom": "Score", - "tableTo": "MatchBlock", + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "TeamInTournament_id_Team_id_fk": { + "name": "TeamInTournament_id_Team_id_fk", + "tableFrom": "TeamInTournament", + "tableTo": "Team", "columnsFrom": [ - "block_id" + "id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", - "onUpdate": "cascade" + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "TeamInTournament_id_id_pk": { + "columns": [ + "id", + "id" + ], + "name": "TeamInTournament_id_id_pk" } }, "uniqueConstraints": {} @@ -1505,241 +1256,322 @@ "name": "TeamScore", "columns": { "id": { - "autoincrement": true, "name": "id", "type": "integer", "primaryKey": true, - "notNull": true + "notNull": true, + "autoincrement": true }, "score": { - "autoincrement": false, "name": "score", "type": "real", "primaryKey": false, - "notNull": true - }, - "freemod": { - "default": false, - "autoincrement": false, - "name": "freemod", - "type": "numeric", - "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, "block_id": { - "autoincrement": false, "name": "block_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, "team_id": { - "autoincrement": false, "name": "team_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false } }, - "compositePrimaryKeys": {}, "indexes": {}, "foreignKeys": { - "TeamScore_team_id_Team_id_fk": { - "name": "TeamScore_team_id_Team_id_fk", + "TeamScore_block_id_MatchBlock_id_fk": { + "name": "TeamScore_block_id_MatchBlock_id_fk", "tableFrom": "TeamScore", - "tableTo": "Team", + "tableTo": "MatchBlock", "columnsFrom": [ - "team_id" + "block_id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", + "onDelete": "cascade", "onUpdate": "cascade" }, - "TeamScore_block_id_MatchBlock_id_fk": { - "name": "TeamScore_block_id_MatchBlock_id_fk", + "TeamScore_team_id_Team_id_fk": { + "name": "TeamScore_team_id_Team_id_fk", "tableFrom": "TeamScore", - "tableTo": "MatchBlock", + "tableTo": "Team", "columnsFrom": [ - "block_id" + "team_id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", + "onDelete": "cascade", "onUpdate": "cascade" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "MappoolInMatch": { - "name": "MappoolInMatch", + "Tournament": { + "name": "Tournament", "columns": { - "mappool_id": { - "autoincrement": false, - "name": "mappool_id", + "id": { + "name": "id", "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "match_id": { + "acronym": { + "name": "acronym", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "settings_id": { + "name": "settings_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allow_registrations": { + "name": "allow_registrations", + "type": "integer", + "primaryKey": false, + "notNull": true, "autoincrement": false, - "name": "match_id", + "default": true + }, + "private": { + "name": "private", "type": "integer", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": { - "MappoolInMatch_mappool_id_match_id_pk": { - "columns": [ - "mappool_id", - "match_id" - ], - "name": "MappoolInMatch_mappool_id_match_id_pk" + "notNull": true, + "autoincrement": false + }, + "team_size": { + "name": "team_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "banner_url": { + "name": "banner_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "icon_url": { + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, "indexes": {}, "foreignKeys": { - "MappoolInMatch_match_id_Match_id_fk": { - "name": "MappoolInMatch_match_id_Match_id_fk", - "tableFrom": "MappoolInMatch", - "tableTo": "Match", - "columnsFrom": [ - "match_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "MappoolInMatch_mappool_id_Mappool_id_fk": { - "name": "MappoolInMatch_mappool_id_Mappool_id_fk", - "tableFrom": "MappoolInMatch", - "tableTo": "Mappool", + "Tournament_settings_id_Settings_id_fk": { + "name": "Tournament_settings_id_Settings_id_fk", + "tableFrom": "Tournament", + "tableTo": "Settings", "columnsFrom": [ - "mappool_id" + "settings_id" ], "columnsTo": [ "id" ], - "onDelete": "restrict", - "onUpdate": "cascade" + "onDelete": "no action", + "onUpdate": "no action" } }, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "_TournamentToUser": { - "name": "_TournamentToUser", + "User": { + "name": "User", "columns": { - "A": { - "autoincrement": false, - "name": "A", + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "country_code": { + "name": "country_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "country_name": { + "name": "country_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cover_url": { + "name": "cover_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pp": { + "name": "pp", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "global_rank": { + "name": "global_rank", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": false, + "autoincrement": false }, - "B": { - "autoincrement": false, - "name": "B", + "country_rank": { + "name": "country_rank", "type": "integer", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": {}, - "indexes": { - "_TournamentToUser_B_index": { - "name": "_TournamentToUser_B_index", - "columns": [ - "B" - ], - "isUnique": false + "notNull": false, + "autoincrement": false }, - "_TournamentToUser_AB_unique": { - "name": "_TournamentToUser_AB_unique", - "columns": [ - "A", - "B" - ], - "isUnique": true - } - }, - "foreignKeys": { - "_TournamentToUser_B_User_id_fk": { - "name": "_TournamentToUser_B_User_id_fk", - "tableFrom": "_TournamentToUser", - "tableTo": "User", - "columnsFrom": [ - "B" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" + "total_score": { + "name": "total_score", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false }, - "_TournamentToUser_A_Tournament_id_fk": { - "name": "_TournamentToUser_A_Tournament_id_fk", - "tableFrom": "_TournamentToUser", - "tableTo": "Tournament", - "columnsFrom": [ - "A" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" + "ranked_score": { + "name": "ranked_score", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hit_accuracy": { + "name": "hit_accuracy", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "play_count": { + "name": "play_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "level": { + "name": "level", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "level_progress": { + "name": "level_progress", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "_ModMultiplierToSettings": { - "name": "_ModMultiplierToSettings", + "UserInTeam": { + "name": "UserInTeam", "columns": { - "A": { - "autoincrement": false, - "name": "A", + "user_id": { + "name": "user_id", "type": "integer", "primaryKey": false, - "notNull": true + "notNull": true, + "autoincrement": false }, - "B": { - "autoincrement": false, - "name": "B", + "team_id": { + "name": "team_id", "type": "integer", "primaryKey": false, - "notNull": true - } - }, - "compositePrimaryKeys": {}, - "indexes": { - "_ModMultiplierToSettings_B_index": { - "name": "_ModMultiplierToSettings_B_index", - "columns": [ - "B" - ], - "isUnique": false + "notNull": true, + "autoincrement": false }, - "_ModMultiplierToSettings_AB_unique": { - "name": "_ModMultiplierToSettings_AB_unique", - "columns": [ - "A", - "B" - ], - "isUnique": true + "invite": { + "name": "invite", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "member_order": { + "name": "member_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 } }, + "indexes": {}, "foreignKeys": { - "_ModMultiplierToSettings_B_TournamentSettings_id_fk": { - "name": "_ModMultiplierToSettings_B_TournamentSettings_id_fk", - "tableFrom": "_ModMultiplierToSettings", - "tableTo": "TournamentSettings", + "UserInTeam_user_id_User_id_fk": { + "name": "UserInTeam_user_id_User_id_fk", + "tableFrom": "UserInTeam", + "tableTo": "User", "columnsFrom": [ - "B" + "user_id" ], "columnsTo": [ "id" @@ -1747,12 +1579,12 @@ "onDelete": "cascade", "onUpdate": "cascade" }, - "_ModMultiplierToSettings_A_ModMultiplier_id_fk": { - "name": "_ModMultiplierToSettings_A_ModMultiplier_id_fk", - "tableFrom": "_ModMultiplierToSettings", - "tableTo": "ModMultiplier", + "UserInTeam_team_id_Team_id_fk": { + "name": "UserInTeam_team_id_Team_id_fk", + "tableFrom": "UserInTeam", + "tableTo": "Team", "columnsFrom": [ - "A" + "team_id" ], "columnsTo": [ "id" @@ -1761,6 +1593,15 @@ "onUpdate": "cascade" } }, + "compositePrimaryKeys": { + "UserInTeam_user_id_team_id_pk": { + "columns": [ + "team_id", + "user_id" + ], + "name": "UserInTeam_user_id_team_id_pk" + } + }, "uniqueConstraints": {} } }, @@ -1769,5 +1610,8 @@ "schemas": {}, "tables": {}, "columns": {} + }, + "internal": { + "indexes": {} } } \ No newline at end of file diff --git a/src/lib/drizzle/meta/_journal.json b/src/lib/drizzle/meta/_journal.json index e4cf9b3..aaeab53 100644 --- a/src/lib/drizzle/meta/_journal.json +++ b/src/lib/drizzle/meta/_journal.json @@ -1,12 +1,12 @@ { "version": "7", - "dialect": "postgresql", + "dialect": "sqlite", "entries": [ { "idx": 0, "version": "6", - "when": 1717281455192, - "tag": "0000_married_human_fly", + "when": 1717292642551, + "tag": "0000_wild_vermin", "breakpoints": true } ] From 2649d364a1778fbbd60d07c24506992d60cc9c14 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sat, 1 Jun 2024 22:27:41 -0400 Subject: [PATCH 05/11] remove prisma & add simple graphql api --- bun.lockb | Bin 207920 -> 135593 bytes package.json | 10 +- prisma/dbml/schema.dbml | 511 --------------- .../20220928204222_first/migration.sql | 373 ----------- .../migrations/20221012211922_/migration.sql | 9 - .../migrations/20221012213724_/migration.sql | 15 - .../migrations/20221012215423_/migration.sql | 54 -- .../migrations/20221012220939_/migration.sql | 16 - .../migrations/20221012221504_/migration.sql | 2 - .../migrations/20221018201142_/migration.sql | 75 --- .../20221229003239_twitch/migration.sql | 51 -- .../20221229015055_bigint/migration.sql | 22 - .../20221229022311_user/migration.sql | 22 - .../migration.sql | 18 - .../20231219172607_snake_case/migration.sql | 594 ------------------ .../migration.sql | 285 --------- .../migration.sql | 67 -- prisma/migrations/migration_lock.toml | 3 - prisma/schema.prisma | 327 ---------- src/index.ts | 32 +- src/prisma.ts | 2 - src/rest/docs/index.ts | 18 - src/rest/index.ts | 10 - src/rest/tournament/get.ts | 76 --- src/rest/tournament/index.ts | 4 - src/ws/index.ts | 5 - 26 files changed, 26 insertions(+), 2575 deletions(-) delete mode 100644 prisma/dbml/schema.dbml delete mode 100644 prisma/migrations/20220928204222_first/migration.sql delete mode 100644 prisma/migrations/20221012211922_/migration.sql delete mode 100644 prisma/migrations/20221012213724_/migration.sql delete mode 100644 prisma/migrations/20221012215423_/migration.sql delete mode 100644 prisma/migrations/20221012220939_/migration.sql delete mode 100644 prisma/migrations/20221012221504_/migration.sql delete mode 100644 prisma/migrations/20221018201142_/migration.sql delete mode 100644 prisma/migrations/20221229003239_twitch/migration.sql delete mode 100644 prisma/migrations/20221229015055_bigint/migration.sql delete mode 100644 prisma/migrations/20221229022311_user/migration.sql delete mode 100644 prisma/migrations/20230828090847_optional_map_mapinpool/migration.sql delete mode 100644 prisma/migrations/20231219172607_snake_case/migration.sql delete mode 100644 prisma/migrations/20231220001634_move_settings/migration.sql delete mode 100644 prisma/migrations/20231220005120_score_improvements/migration.sql delete mode 100644 prisma/migrations/migration_lock.toml delete mode 100644 prisma/schema.prisma delete mode 100644 src/prisma.ts delete mode 100644 src/rest/docs/index.ts delete mode 100644 src/rest/index.ts delete mode 100644 src/rest/tournament/get.ts delete mode 100644 src/rest/tournament/index.ts delete mode 100644 src/ws/index.ts diff --git a/bun.lockb b/bun.lockb index bb3c0f649739979a81f9ed5936d715082edbf801..80c16ba9fd74956687ee440e4d21d245e65b9208 100755 GIT binary patch delta 34717 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 User.id - -Ref: TwitchAccount.osu_id > User.id - -Ref: OsuOauth.user_id - User.id - -Ref: DiscordOauth.user_id - DiscordAccount.id - -Ref: TwitchOauth.user_id - TwitchAccount.id - -Ref: UserSession.osu_id > User.id - -Ref: Tournament.guild_id > Guild.guild_id - -Ref: Tournament.twitch_account_id > TwitchAccount.id - -Ref: TournamentSettings.tournament_id - Tournament.id - -Ref: TournamentSettings.match_id - Match.id - -Ref: ModMultiplier.tournament_id > Tournament.id - -Ref: Round.tournament_id > Tournament.id [delete: Cascade] - -Ref: RoundSettings.round_id - Round.id - -Ref: RoundSettings.match_id - Match.id - -Ref: TeamInvite.invitee_user_id > User.id - -Ref: TeamInvite.team_id > Team.id [delete: Cascade] - -Ref: MapInPool.map_id > Map.id - -Ref: MapInPool.mappool_id > Mappool.id [delete: Cascade] - -Ref: Team.tournament_id > Tournament.id [delete: Cascade] - -Ref: UserInTeam.osu_id > User.id - -Ref: UserInTeam.team_id > Team.id [delete: Cascade] - -Ref: Match.round_id > Round.id - -Ref: TeamInMatch.match_id > Match.id [delete: Cascade] - -Ref: TeamInMatch.team_id > Team.id [delete: Cascade] - -Ref: MapInMatch.(map_identifier, pool_id) > MapInPool.(identifier, mappool_id) [delete: Cascade] - -Ref: MapInMatch.match_id > Match.id [delete: Cascade] - -Ref: MapInMatch.(match_id, protected_by_id) > TeamInMatch.(match_id, team_id) - -Ref: MapInMatch.(match_id, banned_by_id) > TeamInMatch.(match_id, team_id) - -Ref: MapInMatch.(match_id, picked_by_id) > TeamInMatch.(match_id, team_id) - -Ref: MapInMatch.(match_id, won_by_id) > TeamInMatch.(match_id, team_id) - -Ref: MapInMatch.qualifier_id > QualifierMatch.id - -Ref: Score.(map_identifier, match_id) > MapInMatch.(map_identifier, match_id) - -Ref: Score.user_id > User.id - -Ref: Score.team_score_id > TeamScore.id - -Ref: TeamScore.(map_identifier, match_id) > MapInMatch.(map_identifier, match_id) - -Ref: TeamScore.team_id > Team.id - -Ref: MappoolInMatch.mappool_id > Mappool.id - -Ref: MappoolInMatch.match_id > Match.id - -Ref: TeamInQualifierMatch.team_id > Team.id - -Ref: TeamInQualifierMatch.match_id > QualifierMatch.id \ No newline at end of file diff --git a/prisma/migrations/20220928204222_first/migration.sql b/prisma/migrations/20220928204222_first/migration.sql deleted file mode 100644 index 928b986..0000000 --- a/prisma/migrations/20220928204222_first/migration.sql +++ /dev/null @@ -1,373 +0,0 @@ --- CreateTable -CREATE TABLE "Global" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "ties" INTEGER NOT NULL DEFAULT 0 -); - --- CreateTable -CREATE TABLE "OsuBadge" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "awarded_at" DATETIME NOT NULL, - "description" TEXT NOT NULL, - "image_url" TEXT NOT NULL, - "url" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "UserWithOsuBadge" ( - "userId" INTEGER NOT NULL, - "badgeId" INTEGER NOT NULL, - - PRIMARY KEY ("userId", "badgeId"), - CONSTRAINT "UserWithOsuBadge_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserWithOsuBadge_badgeId_fkey" FOREIGN KEY ("badgeId") REFERENCES "OsuBadge" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "CustomBadge" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "awarded_at" DATETIME NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT NOT NULL, - "image_url" TEXT NOT NULL, - "url" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "UserWithCustomBadge" ( - "userId" INTEGER NOT NULL, - "badgeId" INTEGER NOT NULL, - - PRIMARY KEY ("userId", "badgeId"), - CONSTRAINT "UserWithCustomBadge_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserWithCustomBadge_badgeId_fkey" FOREIGN KEY ("badgeId") REFERENCES "CustomBadge" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "UsersHostingTournament" ( - "userId" INTEGER NOT NULL, - "tourney" INTEGER NOT NULL, - - PRIMARY KEY ("userId", "tourney"), - CONSTRAINT "UsersHostingTournament_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UsersHostingTournament_tourney_fkey" FOREIGN KEY ("tourney") REFERENCES "Tournament" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "User" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "country_code" TEXT NOT NULL, - "country_name" TEXT NOT NULL, - "cover_url" TEXT NOT NULL, - "ranked_score" BIGINT NOT NULL, - "play_count" INTEGER NOT NULL, - "total_score" BIGINT NOT NULL, - "pp_rank" INTEGER NOT NULL, - "level" INTEGER NOT NULL, - "level_progress" INTEGER NOT NULL, - "hit_accuracy" REAL NOT NULL, - "pp" REAL NOT NULL, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "type" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "DiscordAccount" ( - "osuId" INTEGER NOT NULL, - "id" TEXT NOT NULL PRIMARY KEY, - "avatar" TEXT NOT NULL, - "discriminator" TEXT NOT NULL, - "flags" INTEGER NOT NULL, - "username" TEXT NOT NULL, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "type" TEXT NOT NULL, - "scope" TEXT NOT NULL, - CONSTRAINT "DiscordAccount_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "UserSession" ( - "id" TEXT NOT NULL PRIMARY KEY, - "osuId" INTEGER NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - CONSTRAINT "UserSession_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "Guild" ( - "guild_id" TEXT NOT NULL PRIMARY KEY, - "change_nickname" BOOLEAN NOT NULL, - "linked_role" TEXT, - "player_role" TEXT, - "match_results_channel" TEXT, - "manager_admin_disabled" BOOLEAN NOT NULL DEFAULT false, - "active_tournament" INTEGER -); - --- CreateTable -CREATE TABLE "Tournament" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "color" TEXT NOT NULL, - "banner_url" TEXT NOT NULL, - "description" TEXT NOT NULL, - "force_nf" BOOLEAN NOT NULL, - "icon_url" TEXT NOT NULL, - "score_mode" INTEGER NOT NULL, - "team_mode" INTEGER NOT NULL, - "team_size" INTEGER NOT NULL, - "x_v_x_mode" INTEGER NOT NULL, - "allow_registrations" BOOLEAN NOT NULL, - "Guild_id" TEXT, - "delete_warning" BOOLEAN, - "fm_mods" INTEGER NOT NULL DEFAULT 1, - "double_pick" INTEGER NOT NULL DEFAULT 1, - "double_ban" INTEGER NOT NULL DEFAULT 1, - "private" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Tournament_Guild_id_fkey" FOREIGN KEY ("Guild_id") REFERENCES "Guild" ("guild_id") ON DELETE SET NULL ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "ModMultiplier" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "tournament_id" INTEGER NOT NULL, - "modString" TEXT NOT NULL, - "matchExactly" BOOLEAN NOT NULL DEFAULT false, - "multiplier" REAL NOT NULL, - CONSTRAINT "ModMultiplier_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "Round" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - "delete_warning" TEXT, - "show_mappool" BOOLEAN NOT NULL, - "tournamentId" INTEGER NOT NULL, - "mappoolId" INTEGER, - CONSTRAINT "Round_tournamentId_fkey" FOREIGN KEY ("tournamentId") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "Round_mappoolId_fkey" FOREIGN KEY ("mappoolId") REFERENCES "Mappool" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "Mappool" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "global" BOOLEAN NOT NULL DEFAULT false, - "tournament_name" TEXT, - "tournament_acronym" TEXT, - "tournament_iteration" TEXT, - "round_name" TEXT, - "round_acronym" TEXT -); - --- CreateTable -CREATE TABLE "MapInPool" ( - "identifier" TEXT NOT NULL, - "mods" TEXT NOT NULL, - "mapId" TEXT NOT NULL, - "modPriority" INTEGER NOT NULL DEFAULT 0, - "mappoolId" INTEGER NOT NULL, - - PRIMARY KEY ("identifier", "mappoolId"), - CONSTRAINT "MapInPool_mapId_fkey" FOREIGN KEY ("mapId") REFERENCES "Map" ("beatmap_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInPool_mappoolId_fkey" FOREIGN KEY ("mappoolId") REFERENCES "Mappool" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "Map" ( - "beatmap_id" TEXT NOT NULL PRIMARY KEY, - "fetch_time" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "approved" TEXT, - "approved_date" DATETIME, - "artist" TEXT, - "artist_unicode" TEXT, - "audio_unavailable" TEXT, - "beatmapset_id" TEXT, - "bpm" TEXT, - "count_normal" TEXT, - "count_slider" TEXT, - "count_spinner" TEXT, - "creator" TEXT, - "creator_id" TEXT, - "diff_aim" TEXT, - "diff_speed" TEXT, - "diff_approach" TEXT, - "diff_drain" TEXT, - "diff_overall" TEXT, - "diff_size" TEXT, - "difficultyrating" TEXT, - "download_unavailable" TEXT, - "favourite_count" TEXT, - "file_md5" TEXT, - "genre_id" TEXT, - "hit_length" TEXT, - "language_id" TEXT, - "last_update" DATETIME, - "max_combo" TEXT, - "mode" TEXT, - "packs" TEXT, - "passcount" TEXT, - "playcount" TEXT, - "rating" TEXT, - "source" TEXT, - "storyboard" TEXT, - "submit_date" DATETIME, - "tags" TEXT, - "title" TEXT, - "title_unicode" TEXT, - "total_length" TEXT, - "version" TEXT, - "video" TEXT -); - --- CreateTable -CREATE TABLE "Team" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL, - "icon_url" TEXT NOT NULL, - "color" TEXT NOT NULL, - "tournamentId" INTEGER NOT NULL, - "scrim" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Team_tournamentId_fkey" FOREIGN KEY ("tournamentId") REFERENCES "Tournament" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "UserInTeam" ( - "osuId" INTEGER NOT NULL, - "teamId" INTEGER NOT NULL, - "member_order" INTEGER NOT NULL DEFAULT 0, - "delete_warning" BOOLEAN, - - PRIMARY KEY ("osuId", "teamId"), - CONSTRAINT "UserInTeam_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserInTeam_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "Match" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "start_time" DATETIME, - "message_id" TEXT, - "channel_id" TEXT, - "mp_link" TEXT, - "waiting_on" INTEGER, - "roundId" INTEGER, - "state" INTEGER NOT NULL, - "scrim" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Match_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "Round" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "ScrimSettings" ( - "matchId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - CONSTRAINT "ScrimSettings_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "Match" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "TeamInMatch" ( - "matchId" INTEGER NOT NULL, - "teamId" INTEGER NOT NULL, - "score" INTEGER NOT NULL, - "roll" INTEGER, - "pick_order" INTEGER, - "ban_order" INTEGER, - "aborts" INTEGER NOT NULL DEFAULT 0, - "faults" INTEGER NOT NULL DEFAULT 0, - "warmed_up" BOOLEAN NOT NULL DEFAULT false, - "winner" BOOLEAN, - - PRIMARY KEY ("teamId", "matchId"), - CONSTRAINT "TeamInMatch_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "Match" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "TeamInMatch_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "MapInMatch" ( - "matchId" INTEGER NOT NULL, - "mapIdentifier" TEXT NOT NULL, - "poolId" INTEGER NOT NULL, - "bannedByTeamId" INTEGER, - "bannedByMatchId" INTEGER, - "pickedByTeamId" INTEGER, - "pickedByMatchId" INTEGER, - "pickNumber" INTEGER, - "pickTeamNumber" INTEGER, - "wonByTeamId" INTEGER, - "wonByMatchId" INTEGER, - - PRIMARY KEY ("mapIdentifier", "matchId"), - CONSTRAINT "MapInMatch_mapIdentifier_poolId_fkey" FOREIGN KEY ("mapIdentifier", "poolId") REFERENCES "MapInPool" ("identifier", "mappoolId") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "Match" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_bannedByMatchId_bannedByTeamId_fkey" FOREIGN KEY ("bannedByMatchId", "bannedByTeamId") REFERENCES "TeamInMatch" ("matchId", "teamId") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_pickedByMatchId_pickedByTeamId_fkey" FOREIGN KEY ("pickedByMatchId", "pickedByTeamId") REFERENCES "TeamInMatch" ("matchId", "teamId") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_wonByMatchId_wonByTeamId_fkey" FOREIGN KEY ("wonByMatchId", "wonByTeamId") REFERENCES "TeamInMatch" ("matchId", "teamId") ON DELETE SET NULL ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "QualifierRound" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "mappoolId" INTEGER NOT NULL, - CONSTRAINT "QualifierRound_mappoolId_fkey" FOREIGN KEY ("mappoolId") REFERENCES "Mappool" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "QualifierMatch" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "map_index" INTEGER NOT NULL DEFAULT 0 -); - --- CreateTable -CREATE TABLE "TeamInQualifierMatch" ( - "teamId" INTEGER NOT NULL, - "matchId" INTEGER NOT NULL, - - PRIMARY KEY ("teamId", "matchId"), - CONSTRAINT "TeamInQualifierMatch_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamInQualifierMatch_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "QualifierMatch" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "AutoHostRotate" ( - "osuId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "mp_link" TEXT NOT NULL, - "min_stars" REAL, - "max_stars" REAL, - "min_length" INTEGER, - "max_length" INTEGER, - "min_rank" INTEGER, - "max_rank" INTEGER, - "currentHostId" INTEGER, - CONSTRAINT "AutoHostRotate_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "AutoHostRotate_currentHostId_fkey" FOREIGN KEY ("currentHostId") REFERENCES "AutoHostRotatePlayer" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "AutoHostRotatePlayer" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "rank" INTEGER NOT NULL, - "lobbyId" INTEGER NOT NULL, - CONSTRAINT "AutoHostRotatePlayer_lobbyId_fkey" FOREIGN KEY ("lobbyId") REFERENCES "AutoHostRotate" ("osuId") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateIndex -CREATE UNIQUE INDEX "Round_mappoolId_key" ON "Round"("mappoolId"); - --- CreateIndex -CREATE UNIQUE INDEX "QualifierRound_mappoolId_key" ON "QualifierRound"("mappoolId"); - --- CreateIndex -CREATE UNIQUE INDEX "AutoHostRotate_currentHostId_key" ON "AutoHostRotate"("currentHostId"); diff --git a/prisma/migrations/20221012211922_/migration.sql b/prisma/migrations/20221012211922_/migration.sql deleted file mode 100644 index 48d5103..0000000 --- a/prisma/migrations/20221012211922_/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ --- CreateTable -CREATE TABLE "TeamInvite" ( - "inviteeUserId" INTEGER NOT NULL, - "teamId" INTEGER NOT NULL, - - PRIMARY KEY ("inviteeUserId", "teamId"), - CONSTRAINT "TeamInvite_inviteeUserId_fkey" FOREIGN KEY ("inviteeUserId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamInvite_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); diff --git a/prisma/migrations/20221012213724_/migration.sql b/prisma/migrations/20221012213724_/migration.sql deleted file mode 100644 index 48dc3f7..0000000 --- a/prisma/migrations/20221012213724_/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_UsersHostingTournament" ( - "userId" INTEGER NOT NULL, - "tourney" INTEGER NOT NULL, - - PRIMARY KEY ("userId", "tourney"), - CONSTRAINT "UsersHostingTournament_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "UsersHostingTournament_tourney_fkey" FOREIGN KEY ("tourney") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UsersHostingTournament" ("tourney", "userId") SELECT "tourney", "userId" FROM "UsersHostingTournament"; -DROP TABLE "UsersHostingTournament"; -ALTER TABLE "new_UsersHostingTournament" RENAME TO "UsersHostingTournament"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221012215423_/migration.sql b/prisma/migrations/20221012215423_/migration.sql deleted file mode 100644 index a3812ec..0000000 --- a/prisma/migrations/20221012215423_/migration.sql +++ /dev/null @@ -1,54 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_MapInPool" ( - "identifier" TEXT NOT NULL, - "mods" TEXT NOT NULL, - "mapId" TEXT NOT NULL, - "modPriority" INTEGER NOT NULL DEFAULT 0, - "mappoolId" INTEGER NOT NULL, - - PRIMARY KEY ("identifier", "mappoolId"), - CONSTRAINT "MapInPool_mapId_fkey" FOREIGN KEY ("mapId") REFERENCES "Map" ("beatmap_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInPool_mappoolId_fkey" FOREIGN KEY ("mappoolId") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_MapInPool" ("identifier", "mapId", "mappoolId", "modPriority", "mods") SELECT "identifier", "mapId", "mappoolId", "modPriority", "mods" FROM "MapInPool"; -DROP TABLE "MapInPool"; -ALTER TABLE "new_MapInPool" RENAME TO "MapInPool"; -CREATE TABLE "new_UserInTeam" ( - "osuId" INTEGER NOT NULL, - "teamId" INTEGER NOT NULL, - "member_order" INTEGER NOT NULL DEFAULT 0, - "delete_warning" BOOLEAN, - - PRIMARY KEY ("osuId", "teamId"), - CONSTRAINT "UserInTeam_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserInTeam_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UserInTeam" ("delete_warning", "member_order", "osuId", "teamId") SELECT "delete_warning", "member_order", "osuId", "teamId" FROM "UserInTeam"; -DROP TABLE "UserInTeam"; -ALTER TABLE "new_UserInTeam" RENAME TO "UserInTeam"; -CREATE TABLE "new_Team" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL, - "icon_url" TEXT NOT NULL, - "color" TEXT NOT NULL, - "tournamentId" INTEGER NOT NULL, - "scrim" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Team_tournamentId_fkey" FOREIGN KEY ("tournamentId") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_Team" ("color", "icon_url", "id", "name", "scrim", "tournamentId") SELECT "color", "icon_url", "id", "name", "scrim", "tournamentId" FROM "Team"; -DROP TABLE "Team"; -ALTER TABLE "new_Team" RENAME TO "Team"; -CREATE TABLE "new_TeamInvite" ( - "inviteeUserId" INTEGER NOT NULL, - "teamId" INTEGER NOT NULL, - - PRIMARY KEY ("inviteeUserId", "teamId"), - CONSTRAINT "TeamInvite_inviteeUserId_fkey" FOREIGN KEY ("inviteeUserId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamInvite_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_TeamInvite" ("inviteeUserId", "teamId") SELECT "inviteeUserId", "teamId" FROM "TeamInvite"; -DROP TABLE "TeamInvite"; -ALTER TABLE "new_TeamInvite" RENAME TO "TeamInvite"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221012220939_/migration.sql b/prisma/migrations/20221012220939_/migration.sql deleted file mode 100644 index 395a4b1..0000000 --- a/prisma/migrations/20221012220939_/migration.sql +++ /dev/null @@ -1,16 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_UserSession" ( - "id" TEXT NOT NULL PRIMARY KEY, - "osuId" INTEGER NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "lastUsed" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "device" TEXT, - "browser" TEXT, - CONSTRAINT "UserSession_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_UserSession" ("createdAt", "id", "osuId") SELECT "createdAt", "id", "osuId" FROM "UserSession"; -DROP TABLE "UserSession"; -ALTER TABLE "new_UserSession" RENAME TO "UserSession"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221012221504_/migration.sql b/prisma/migrations/20221012221504_/migration.sql deleted file mode 100644 index 75cfda6..0000000 --- a/prisma/migrations/20221012221504_/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "UserSession" ADD COLUMN "os" TEXT; diff --git a/prisma/migrations/20221018201142_/migration.sql b/prisma/migrations/20221018201142_/migration.sql deleted file mode 100644 index 997abf8..0000000 --- a/prisma/migrations/20221018201142_/migration.sql +++ /dev/null @@ -1,75 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `access_token` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `expires_in` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `last_update` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `refresh_token` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `type` on the `User` table. All the data in the column will be lost. - - You are about to drop the column `access_token` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `expires_in` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `last_update` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `refresh_token` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `scope` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `type` on the `DiscordAccount` table. All the data in the column will be lost. - -*/ --- CreateTable -CREATE TABLE "OsuOauth" ( - "userId" INTEGER NOT NULL PRIMARY KEY, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - CONSTRAINT "OsuOauth_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "OsuOauth" ("userId", "last_update", "access_token", "expires_in", "refresh_token", "token_type") SELECT "id", "last_update", "access_token", "expires_in", "refresh_token", "type" FROM "User"; - --- CreateTable -CREATE TABLE "DiscordOauth" ( - "userId" TEXT NOT NULL PRIMARY KEY, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - "scope" TEXT NOT NULL, - CONSTRAINT "DiscordOauth_userId_fkey" FOREIGN KEY ("userId") REFERENCES "DiscordAccount" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "DiscordOauth" ("userId", "last_update", "access_token", "expires_in", "refresh_token", "token_type", "scope") SELECT "id", "last_update", "access_token", "expires_in", "refresh_token", "type", "SCOPE" FROM "DiscordAccount"; - --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_User" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "country_code" TEXT NOT NULL, - "country_name" TEXT NOT NULL, - "cover_url" TEXT NOT NULL, - "ranked_score" BIGINT NOT NULL, - "play_count" INTEGER NOT NULL, - "total_score" BIGINT NOT NULL, - "pp_rank" INTEGER NOT NULL, - "level" INTEGER NOT NULL, - "level_progress" INTEGER NOT NULL, - "hit_accuracy" REAL NOT NULL, - "pp" REAL NOT NULL -); -INSERT INTO "new_User" ("country_code", "country_name", "cover_url", "hit_accuracy", "id", "level", "level_progress", "play_count", "pp", "pp_rank", "ranked_score", "total_score", "username") SELECT "country_code", "country_name", "cover_url", "hit_accuracy", "id", "level", "level_progress", "play_count", "pp", "pp_rank", "ranked_score", "total_score", "username" FROM "User"; -DROP TABLE "User"; -ALTER TABLE "new_User" RENAME TO "User"; -CREATE TABLE "new_DiscordAccount" ( - "osuId" INTEGER NOT NULL, - "id" TEXT NOT NULL PRIMARY KEY, - "avatar" TEXT NOT NULL, - "discriminator" TEXT NOT NULL, - "flags" INTEGER NOT NULL, - "username" TEXT NOT NULL, - CONSTRAINT "DiscordAccount_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_DiscordAccount" ("avatar", "discriminator", "flags", "id", "osuId", "username") SELECT "avatar", "discriminator", "flags", "id", "osuId", "username" FROM "DiscordAccount"; -DROP TABLE "DiscordAccount"; -ALTER TABLE "new_DiscordAccount" RENAME TO "DiscordAccount"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221229003239_twitch/migration.sql b/prisma/migrations/20221229003239_twitch/migration.sql deleted file mode 100644 index e291700..0000000 --- a/prisma/migrations/20221229003239_twitch/migration.sql +++ /dev/null @@ -1,51 +0,0 @@ --- CreateTable -CREATE TABLE "TwitchAccount" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "requests_enabled" BOOLEAN NOT NULL DEFAULT false, - "req_require_live" BOOLEAN NOT NULL DEFAULT false, - "req_require_category" BOOLEAN NOT NULL DEFAULT false -); - --- CreateTable -CREATE TABLE "TwitchOauth" ( - "userId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_at" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - CONSTRAINT "TwitchOauth_userId_fkey" FOREIGN KEY ("userId") REFERENCES "TwitchAccount" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_Tournament" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "color" TEXT NOT NULL, - "banner_url" TEXT NOT NULL, - "description" TEXT NOT NULL, - "force_nf" BOOLEAN NOT NULL, - "icon_url" TEXT NOT NULL, - "score_mode" INTEGER NOT NULL, - "team_mode" INTEGER NOT NULL, - "team_size" INTEGER NOT NULL, - "x_v_x_mode" INTEGER NOT NULL, - "allow_registrations" BOOLEAN NOT NULL, - "Guild_id" TEXT, - "delete_warning" BOOLEAN, - "fm_mods" INTEGER NOT NULL DEFAULT 1, - "double_pick" INTEGER NOT NULL DEFAULT 1, - "double_ban" INTEGER NOT NULL DEFAULT 1, - "private" BOOLEAN NOT NULL DEFAULT false, - "twitchAccountId" INTEGER, - CONSTRAINT "Tournament_Guild_id_fkey" FOREIGN KEY ("Guild_id") REFERENCES "Guild" ("guild_id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "Tournament_twitchAccountId_fkey" FOREIGN KEY ("twitchAccountId") REFERENCES "TwitchAccount" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_Tournament" ("Guild_id", "acronym", "allow_registrations", "banner_url", "color", "delete_warning", "description", "double_ban", "double_pick", "fm_mods", "force_nf", "icon_url", "id", "name", "private", "score_mode", "team_mode", "team_size", "x_v_x_mode") SELECT "Guild_id", "acronym", "allow_registrations", "banner_url", "color", "delete_warning", "description", "double_ban", "double_pick", "fm_mods", "force_nf", "icon_url", "id", "name", "private", "score_mode", "team_mode", "team_size", "x_v_x_mode" FROM "Tournament"; -DROP TABLE "Tournament"; -ALTER TABLE "new_Tournament" RENAME TO "Tournament"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221229015055_bigint/migration.sql b/prisma/migrations/20221229015055_bigint/migration.sql deleted file mode 100644 index 0ee994c..0000000 --- a/prisma/migrations/20221229015055_bigint/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - Warnings: - - - You are about to alter the column `expires_at` on the `TwitchOauth` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`. - -*/ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_TwitchOauth" ( - "userId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_at" BIGINT NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - CONSTRAINT "TwitchOauth_userId_fkey" FOREIGN KEY ("userId") REFERENCES "TwitchAccount" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_TwitchOauth" ("access_token", "expires_at", "last_update", "refresh_token", "token_type", "userId") SELECT "access_token", "expires_at", "last_update", "refresh_token", "token_type", "userId" FROM "TwitchOauth"; -DROP TABLE "TwitchOauth"; -ALTER TABLE "new_TwitchOauth" RENAME TO "TwitchOauth"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20221229022311_user/migration.sql b/prisma/migrations/20221229022311_user/migration.sql deleted file mode 100644 index 02c88ad..0000000 --- a/prisma/migrations/20221229022311_user/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - Warnings: - - - Added the required column `osuId` to the `TwitchAccount` table without a default value. This is not possible if the table is not empty. - -*/ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_TwitchAccount" ( - "osuId" INTEGER NOT NULL, - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "requests_enabled" BOOLEAN NOT NULL DEFAULT false, - "req_require_live" BOOLEAN NOT NULL DEFAULT false, - "req_require_category" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "TwitchAccount_osuId_fkey" FOREIGN KEY ("osuId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_TwitchAccount" ("id", "req_require_category", "req_require_live", "requests_enabled", "username") SELECT "id", "req_require_category", "req_require_live", "requests_enabled", "username" FROM "TwitchAccount"; -DROP TABLE "TwitchAccount"; -ALTER TABLE "new_TwitchAccount" RENAME TO "TwitchAccount"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20230828090847_optional_map_mapinpool/migration.sql b/prisma/migrations/20230828090847_optional_map_mapinpool/migration.sql deleted file mode 100644 index 96a5143..0000000 --- a/prisma/migrations/20230828090847_optional_map_mapinpool/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_MapInPool" ( - "identifier" TEXT NOT NULL, - "mods" TEXT NOT NULL, - "mapId" TEXT, - "modPriority" INTEGER NOT NULL DEFAULT 0, - "mappoolId" INTEGER NOT NULL, - - PRIMARY KEY ("identifier", "mappoolId"), - CONSTRAINT "MapInPool_mapId_fkey" FOREIGN KEY ("mapId") REFERENCES "Map" ("beatmap_id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "MapInPool_mappoolId_fkey" FOREIGN KEY ("mappoolId") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_MapInPool" ("identifier", "mapId", "mappoolId", "modPriority", "mods") SELECT "identifier", "mapId", "mappoolId", "modPriority", "mods" FROM "MapInPool"; -DROP TABLE "MapInPool"; -ALTER TABLE "new_MapInPool" RENAME TO "MapInPool"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20231219172607_snake_case/migration.sql b/prisma/migrations/20231219172607_snake_case/migration.sql deleted file mode 100644 index 61c0c24..0000000 --- a/prisma/migrations/20231219172607_snake_case/migration.sql +++ /dev/null @@ -1,594 +0,0 @@ -/* - Warnings: - - - You are about to drop the `QualifierRound` table. If the table is not empty, all the data it contains will be lost. - - The primary key for the `OsuOauth` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `userId` on the `OsuOauth` table. All the data in the column will be lost. - - You are about to drop the column `osuId` on the `DiscordAccount` table. All the data in the column will be lost. - - You are about to drop the column `osuId` on the `TwitchAccount` table. All the data in the column will be lost. - - The primary key for the `TwitchOauth` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `userId` on the `TwitchOauth` table. All the data in the column will be lost. - - The primary key for the `DiscordOauth` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `userId` on the `DiscordOauth` table. All the data in the column will be lost. - - You are about to drop the column `lobbyId` on the `AutoHostRotatePlayer` table. All the data in the column will be lost. - - You are about to drop the column `matchExactly` on the `ModMultiplier` table. All the data in the column will be lost. - - You are about to drop the column `modString` on the `ModMultiplier` table. All the data in the column will be lost. - - The primary key for the `MapInMatch` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `bannedByMatchId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `bannedByTeamId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `mapIdentifier` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `matchId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `pickNumber` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `pickTeamNumber` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `pickedByMatchId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `pickedByTeamId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `poolId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `wonByMatchId` on the `MapInMatch` table. All the data in the column will be lost. - - You are about to drop the column `wonByTeamId` on the `MapInMatch` table. All the data in the column will be lost. - - The primary key for the `TeamInMatch` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `matchId` on the `TeamInMatch` table. All the data in the column will be lost. - - You are about to drop the column `teamId` on the `TeamInMatch` table. All the data in the column will be lost. - - The primary key for the `AutoHostRotate` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `currentHostId` on the `AutoHostRotate` table. All the data in the column will be lost. - - You are about to drop the column `osuId` on the `AutoHostRotate` table. All the data in the column will be lost. - - The primary key for the `ScrimSettings` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `matchId` on the `ScrimSettings` table. All the data in the column will be lost. - - You are about to drop the column `global` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `round_acronym` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `round_name` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `tournament_acronym` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `tournament_iteration` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `tournament_name` on the `Mappool` table. All the data in the column will be lost. - - You are about to drop the column `roundId` on the `Match` table. All the data in the column will be lost. - - The primary key for the `UserInTeam` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `osuId` on the `UserInTeam` table. All the data in the column will be lost. - - You are about to drop the column `teamId` on the `UserInTeam` table. All the data in the column will be lost. - - The primary key for the `TeamInvite` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `inviteeUserId` on the `TeamInvite` table. All the data in the column will be lost. - - You are about to drop the column `teamId` on the `TeamInvite` table. All the data in the column will be lost. - - You are about to drop the column `Guild_id` on the `Tournament` table. All the data in the column will be lost. - - You are about to drop the column `twitchAccountId` on the `Tournament` table. All the data in the column will be lost. - - The primary key for the `Map` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `approved` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `approved_date` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `audio_unavailable` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `beatmap_id` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `count_normal` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `count_slider` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `count_spinner` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `creator` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `creator_id` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_aim` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_approach` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_drain` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_overall` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_size` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `diff_speed` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `difficultyrating` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `download_unavailable` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `favourite_count` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `file_md5` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `genre_id` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `language_id` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `last_update` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `mode` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `packs` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `passcount` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `playcount` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `rating` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `source` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `storyboard` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `submit_date` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `tags` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `version` on the `Map` table. All the data in the column will be lost. - - You are about to drop the column `video` on the `Map` table. All the data in the column will be lost. - - You are about to alter the column `beatmapset_id` on the `Map` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. - - You are about to alter the column `bpm` on the `Map` table. The data in that column could be lost. The data in that column will be cast from `String` to `Float`. - - You are about to alter the column `hit_length` on the `Map` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. - - You are about to alter the column `max_combo` on the `Map` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. - - You are about to alter the column `total_length` on the `Map` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`. - - You are about to drop the column `createdAt` on the `UserSession` table. All the data in the column will be lost. - - You are about to drop the column `lastUsed` on the `UserSession` table. All the data in the column will be lost. - - You are about to drop the column `osuId` on the `UserSession` table. All the data in the column will be lost. - - You are about to drop the column `tournamentId` on the `Team` table. All the data in the column will be lost. - - The primary key for the `UserWithCustomBadge` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `badgeId` on the `UserWithCustomBadge` table. All the data in the column will be lost. - - You are about to drop the column `userId` on the `UserWithCustomBadge` table. All the data in the column will be lost. - - The primary key for the `UserWithOsuBadge` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `badgeId` on the `UserWithOsuBadge` table. All the data in the column will be lost. - - You are about to drop the column `userId` on the `UserWithOsuBadge` table. All the data in the column will be lost. - - You are about to drop the column `mappoolId` on the `Round` table. All the data in the column will be lost. - - You are about to drop the column `show_mappool` on the `Round` table. All the data in the column will be lost. - - You are about to drop the column `tournamentId` on the `Round` table. All the data in the column will be lost. - - The primary key for the `UsersHostingTournament` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `tourney` on the `UsersHostingTournament` table. All the data in the column will be lost. - - You are about to drop the column `userId` on the `UsersHostingTournament` table. All the data in the column will be lost. - - The primary key for the `MapInPool` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `mapId` on the `MapInPool` table. All the data in the column will be lost. - - You are about to drop the column `mappoolId` on the `MapInPool` table. All the data in the column will be lost. - - You are about to drop the column `modPriority` on the `MapInPool` table. All the data in the column will be lost. - - The primary key for the `TeamInQualifierMatch` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `matchId` on the `TeamInQualifierMatch` table. All the data in the column will be lost. - - You are about to drop the column `teamId` on the `TeamInQualifierMatch` table. All the data in the column will be lost. - - Added the required column `user_id` to the `OsuOauth` table without a default value. This is not possible if the table is not empty. - - Added the required column `osu_id` to the `DiscordAccount` table without a default value. This is not possible if the table is not empty. - - Added the required column `osu_id` to the `TwitchAccount` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `TwitchOauth` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `DiscordOauth` table without a default value. This is not possible if the table is not empty. - - Added the required column `lobby_id` to the `AutoHostRotatePlayer` table without a default value. This is not possible if the table is not empty. - - Added the required column `mod_string` to the `ModMultiplier` table without a default value. This is not possible if the table is not empty. - - Added the required column `map_identifier` to the `MapInMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `match_id` to the `MapInMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `pool_id` to the `MapInMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `match_id` to the `TeamInMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `team_id` to the `TeamInMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `osu_id` to the `AutoHostRotate` table without a default value. This is not possible if the table is not empty. - - Added the required column `match_id` to the `ScrimSettings` table without a default value. This is not possible if the table is not empty. - - Added the required column `name` to the `Mappool` table without a default value. This is not possible if the table is not empty. - - Added the required column `osu_id` to the `UserInTeam` table without a default value. This is not possible if the table is not empty. - - Added the required column `team_id` to the `UserInTeam` table without a default value. This is not possible if the table is not empty. - - Added the required column `invitee_user_id` to the `TeamInvite` table without a default value. This is not possible if the table is not empty. - - Added the required column `team_id` to the `TeamInvite` table without a default value. This is not possible if the table is not empty. - - Added the required column `aim_difficulty` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `approach_rate` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `available` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `card_2x_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `card_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `circle_size` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `count_circles` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `count_sliders` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `count_spinners` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `cover_2x_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `cover_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `diff_mapper_user_id` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `difficulty_name` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `flashlight_difficulty` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `hp_drain` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `id` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `last_updated` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `list_2x_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `list_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `overall_difficulty` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `preview_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `set_mapper_user_id` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `slider_factor` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `slim_cover_2x_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `slim_cover_url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `speed_difficulty` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `star_rating` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `status` to the `Map` table without a default value. This is not possible if the table is not empty. - - Added the required column `url` to the `Map` table without a default value. This is not possible if the table is not empty. - - Made the column `artist` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `artist_unicode` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `beatmapset_id` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `bpm` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `hit_length` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `max_combo` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `title` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `title_unicode` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Made the column `total_length` on table `Map` required. This step will fail if there are existing NULL values in that column. - - Added the required column `osu_id` to the `UserSession` table without a default value. This is not possible if the table is not empty. - - Added the required column `tournament_id` to the `Team` table without a default value. This is not possible if the table is not empty. - - Added the required column `badge_id` to the `UserWithCustomBadge` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `UserWithCustomBadge` table without a default value. This is not possible if the table is not empty. - - Added the required column `badge_id` to the `UserWithOsuBadge` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `UserWithOsuBadge` table without a default value. This is not possible if the table is not empty. - - Added the required column `tournament_id` to the `Round` table without a default value. This is not possible if the table is not empty. - - Added the required column `tournament_id` to the `UsersHostingTournament` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `UsersHostingTournament` table without a default value. This is not possible if the table is not empty. - - Added the required column `mappool_id` to the `MapInPool` table without a default value. This is not possible if the table is not empty. - - Added the required column `match_id` to the `TeamInQualifierMatch` table without a default value. This is not possible if the table is not empty. - - Added the required column `team_id` to the `TeamInQualifierMatch` table without a default value. This is not possible if the table is not empty. - -*/ --- DropIndex -DROP INDEX "QualifierRound_mappoolId_key"; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "QualifierRound"; -PRAGMA foreign_keys=on; - --- CreateTable -CREATE TABLE "MappoolInRound" ( - "round_id" INTEGER NOT NULL, - "mappool_id" INTEGER NOT NULL, - - PRIMARY KEY ("round_id", "mappool_id"), - CONSTRAINT "MappoolInRound_round_id_fkey" FOREIGN KEY ("round_id") REFERENCES "Round" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MappoolInRound_mappool_id_fkey" FOREIGN KEY ("mappool_id") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "_MappoolToRound" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL, - CONSTRAINT "_MappoolToRound_A_fkey" FOREIGN KEY ("A") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "_MappoolToRound_B_fkey" FOREIGN KEY ("B") REFERENCES "Round" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "_MapToMappool" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL, - CONSTRAINT "_MapToMappool_A_fkey" FOREIGN KEY ("A") REFERENCES "Map" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "_MapToMappool_B_fkey" FOREIGN KEY ("B") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_OsuOauth" ( - "user_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - CONSTRAINT "OsuOauth_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_OsuOauth" ("user_id", "access_token", "expires_in", "last_update", "refresh_token", "token_type") SELECT "userId", "access_token", "expires_in", "last_update", "refresh_token", "token_type" FROM "OsuOauth"; -DROP TABLE "OsuOauth"; -ALTER TABLE "new_OsuOauth" RENAME TO "OsuOauth"; -CREATE TABLE "new_DiscordAccount" ( - "osu_id" INTEGER NOT NULL, - "id" TEXT NOT NULL PRIMARY KEY, - "avatar" TEXT NOT NULL, - "discriminator" TEXT NOT NULL, - "flags" INTEGER NOT NULL, - "username" TEXT NOT NULL, - CONSTRAINT "DiscordAccount_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_DiscordAccount" ("osu_id", "avatar", "discriminator", "flags", "id", "username") SELECT "osuId", "avatar", "discriminator", "flags", "id", "username" FROM "DiscordAccount"; -DROP TABLE "DiscordAccount"; -ALTER TABLE "new_DiscordAccount" RENAME TO "DiscordAccount"; -CREATE TABLE "new_TwitchAccount" ( - "osu_id" INTEGER NOT NULL, - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "requests_enabled" BOOLEAN NOT NULL DEFAULT false, - "req_require_live" BOOLEAN NOT NULL DEFAULT false, - "req_require_category" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "TwitchAccount_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_TwitchAccount" ("osu_id", "id", "req_require_category", "req_require_live", "requests_enabled", "username") SELECT "osuId", "id", "req_require_category", "req_require_live", "requests_enabled", "username" FROM "TwitchAccount"; -DROP TABLE "TwitchAccount"; -ALTER TABLE "new_TwitchAccount" RENAME TO "TwitchAccount"; -CREATE TABLE "new_TwitchOauth" ( - "user_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_at" BIGINT NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - CONSTRAINT "TwitchOauth_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "TwitchAccount" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_TwitchOauth" ("user_id", "access_token", "expires_at", "last_update", "refresh_token", "token_type") SELECT "userId", "access_token", "expires_at", "last_update", "refresh_token", "token_type" FROM "TwitchOauth"; -DROP TABLE "TwitchOauth"; -ALTER TABLE "new_TwitchOauth" RENAME TO "TwitchOauth"; -CREATE TABLE "new_DiscordOauth" ( - "user_id" TEXT NOT NULL PRIMARY KEY, - "last_update" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "access_token" TEXT NOT NULL, - "expires_in" INTEGER NOT NULL, - "refresh_token" TEXT NOT NULL, - "token_type" TEXT NOT NULL, - "scope" TEXT NOT NULL, - CONSTRAINT "DiscordOauth_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "DiscordAccount" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_DiscordOauth" ("user_id", "access_token", "expires_in", "last_update", "refresh_token", "scope", "token_type") SELECT "userId", "access_token", "expires_in", "last_update", "refresh_token", "scope", "token_type" FROM "DiscordOauth"; -DROP TABLE "DiscordOauth"; -ALTER TABLE "new_DiscordOauth" RENAME TO "DiscordOauth"; -CREATE TABLE "new_AutoHostRotatePlayer" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "username" TEXT NOT NULL, - "rank" INTEGER NOT NULL, - "lobby_id" INTEGER NOT NULL, - CONSTRAINT "AutoHostRotatePlayer_lobby_id_fkey" FOREIGN KEY ("lobby_id") REFERENCES "AutoHostRotate" ("osu_id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_AutoHostRotatePlayer" ("id", "rank", "username", "lobby_id") SELECT "id", "rank", "username", "lobbyId" FROM "AutoHostRotatePlayer"; -DROP TABLE "AutoHostRotatePlayer"; -ALTER TABLE "new_AutoHostRotatePlayer" RENAME TO "AutoHostRotatePlayer"; -CREATE TABLE "new_ModMultiplier" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "tournament_id" INTEGER NOT NULL, - "mod_string" TEXT NOT NULL, - "match_exactly" BOOLEAN NOT NULL DEFAULT false, - "multiplier" REAL NOT NULL, - CONSTRAINT "ModMultiplier_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_ModMultiplier" ("id", "multiplier", "tournament_id", "mod_string", "match_exactly") SELECT "id", "multiplier", "tournamentId", "modString", "matchExactly" FROM "ModMultiplier"; -DROP TABLE "ModMultiplier"; -ALTER TABLE "new_ModMultiplier" RENAME TO "ModMultiplier"; -CREATE TABLE "new_MapInMatch" ( - "match_id" INTEGER NOT NULL, - "map_identifier" TEXT NOT NULL, - "pool_id" INTEGER NOT NULL, - "banned_by_id" INTEGER, - "picked_by_id" INTEGER, - "pick_number" INTEGER, - "pick_team_number" INTEGER, - "won_by_id" INTEGER, - - PRIMARY KEY ("map_identifier", "match_id"), - CONSTRAINT "MapInMatch_map_identifier_pool_id_fkey" FOREIGN KEY ("map_identifier", "pool_id") REFERENCES "MapInPool" ("identifier", "mappool_id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_banned_by_id_fkey" FOREIGN KEY ("match_id", "banned_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_picked_by_id_fkey" FOREIGN KEY ("match_id", "picked_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_won_by_id_fkey" FOREIGN KEY ("match_id", "won_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_MapInMatch" ("map_identifier", "match_id", "pool_id", "banned_by_id", "picked_by_id", "pick_number", "pick_team_number", "won_by_id") SELECT "mapIdentifier", "matchId", "poolId", "bannedByTeamId", "pickedByTeamId", "pickNumber", "pickTeamNumber", "wonByTeamId" FROM "MapInMatch"; -DROP TABLE "MapInMatch"; -ALTER TABLE "new_MapInMatch" RENAME TO "MapInMatch"; -CREATE TABLE "new_TeamInMatch" ( - "match_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - "score" INTEGER NOT NULL, - "roll" INTEGER, - "pick_order" INTEGER, - "ban_order" INTEGER, - "aborts" INTEGER NOT NULL DEFAULT 0, - "faults" INTEGER NOT NULL DEFAULT 0, - "warmed_up" BOOLEAN NOT NULL DEFAULT false, - "winner" BOOLEAN, - - PRIMARY KEY ("team_id", "match_id"), - CONSTRAINT "TeamInMatch_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "TeamInMatch_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_TeamInMatch" ("team_id", "match_id", "aborts", "ban_order", "faults", "pick_order", "roll", "score", "warmed_up", "winner") SELECT "teamId", "matchId", "aborts", "ban_order", "faults", "pick_order", "roll", "score", "warmed_up", "winner" FROM "TeamInMatch"; -DROP TABLE "TeamInMatch"; -ALTER TABLE "new_TeamInMatch" RENAME TO "TeamInMatch"; -CREATE TABLE "new_AutoHostRotate" ( - "osu_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "mp_link" TEXT NOT NULL, - "min_stars" REAL, - "max_stars" REAL, - "min_length" INTEGER, - "max_length" INTEGER, - "min_rank" INTEGER, - "max_rank" INTEGER, - "current_host_id" INTEGER, - CONSTRAINT "AutoHostRotate_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "AutoHostRotate_current_host_id_fkey" FOREIGN KEY ("current_host_id") REFERENCES "AutoHostRotatePlayer" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_AutoHostRotate" ("osu_id", "max_length", "max_rank", "max_stars", "min_length", "min_rank", "min_stars", "mp_link", "current_host_id") SELECT "osuId", "max_length", "max_rank", "max_stars", "min_length", "min_rank", "min_stars", "mp_link", "current_host_id" FROM "AutoHostRotate"; -DROP TABLE "AutoHostRotate"; -ALTER TABLE "new_AutoHostRotate" RENAME TO "AutoHostRotate"; -CREATE UNIQUE INDEX "AutoHostRotate_current_host_id_key" ON "AutoHostRotate"("current_host_id"); -CREATE TABLE "new_ScrimSettings" ( - "match_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - CONSTRAINT "ScrimSettings_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_ScrimSettings" ("match_id", "bans", "best_of") SELECT "matchId", "bans", "best_of" FROM "ScrimSettings"; -DROP TABLE "ScrimSettings"; -ALTER TABLE "new_ScrimSettings" RENAME TO "ScrimSettings"; -CREATE TABLE "new_Mappool" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL DEFAULT "New Mappool", - "description" TEXT, - "public" BOOLEAN NOT NULL DEFAULT false -); -INSERT INTO "new_Mappool" ("id", "public") SELECT "id", "global" FROM "Mappool"; -DROP TABLE "Mappool"; -ALTER TABLE "new_Mappool" RENAME TO "Mappool"; -CREATE TABLE "new_Match" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "start_time" DATETIME, - "message_id" TEXT, - "channel_id" TEXT, - "mp_link" TEXT, - "waiting_on" INTEGER, - "round_id" INTEGER, - "state" INTEGER NOT NULL, - "scrim" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Match_round_id_fkey" FOREIGN KEY ("round_id") REFERENCES "Round" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_Match" ("round_id", "channel_id", "id", "message_id", "mp_link", "scrim", "start_time", "state", "waiting_on") SELECT "roundId", "channel_id", "id", "message_id", "mp_link", "scrim", "start_time", "state", "waiting_on" FROM "Match"; -DROP TABLE "Match"; -ALTER TABLE "new_Match" RENAME TO "Match"; -CREATE TABLE "new_UserInTeam" ( - "osu_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - "member_order" INTEGER NOT NULL DEFAULT 0, - "delete_warning" BOOLEAN, - - PRIMARY KEY ("osu_id", "team_id"), - CONSTRAINT "UserInTeam_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserInTeam_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UserInTeam" ("osu_id", "team_id", "delete_warning", "member_order") SELECT "osuId", "teamId", "delete_warning", "member_order" FROM "UserInTeam"; -DROP TABLE "UserInTeam"; -ALTER TABLE "new_UserInTeam" RENAME TO "UserInTeam"; -CREATE TABLE "new_TeamInvite" ( - "invitee_user_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - - PRIMARY KEY ("invitee_user_id", "team_id"), - CONSTRAINT "TeamInvite_invitee_user_id_fkey" FOREIGN KEY ("invitee_user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamInvite_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_TeamInvite" ("invitee_user_id", "team_id") SELECT "inviteeUserId", "teamId" FROM "TeamInvite"; -DROP TABLE "TeamInvite"; -ALTER TABLE "new_TeamInvite" RENAME TO "TeamInvite"; -CREATE TABLE "new_Tournament" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "color" TEXT NOT NULL, - "banner_url" TEXT NOT NULL, - "description" TEXT NOT NULL, - "force_nf" BOOLEAN NOT NULL, - "icon_url" TEXT NOT NULL, - "score_mode" INTEGER NOT NULL, - "team_mode" INTEGER NOT NULL, - "team_size" INTEGER NOT NULL, - "x_v_x_mode" INTEGER NOT NULL, - "allow_registrations" BOOLEAN NOT NULL, - "guild_id" TEXT, - "delete_warning" BOOLEAN, - "fm_mods" INTEGER NOT NULL DEFAULT 1, - "double_pick" INTEGER NOT NULL DEFAULT 1, - "double_ban" INTEGER NOT NULL DEFAULT 1, - "private" BOOLEAN NOT NULL DEFAULT false, - "twitch_account_id" INTEGER, - CONSTRAINT "Tournament_guild_id_fkey" FOREIGN KEY ("guild_id") REFERENCES "Guild" ("guild_id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "Tournament_twitch_account_id_fkey" FOREIGN KEY ("twitch_account_id") REFERENCES "TwitchAccount" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_Tournament" ("guild_id", "twitch_account_id", "acronym", "allow_registrations", "banner_url", "color", "delete_warning", "description", "double_ban", "double_pick", "fm_mods", "force_nf", "icon_url", "id", "name", "private", "score_mode", "team_mode", "team_size", "x_v_x_mode") SELECT "Guild_id", "twitchAccountId", "acronym", "allow_registrations", "banner_url", "color", "delete_warning", "description", "double_ban", "double_pick", "fm_mods", "force_nf", "icon_url", "id", "name", "private", "score_mode", "team_mode", "team_size", "x_v_x_mode" FROM "Tournament"; -DROP TABLE "Tournament"; -ALTER TABLE "new_Tournament" RENAME TO "Tournament"; -CREATE TABLE "new_Map" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "beatmapset_id" INTEGER NOT NULL, - "star_rating" REAL NOT NULL, - "status" TEXT NOT NULL, - "total_length" INTEGER NOT NULL, - "diff_mapper_user_id" INTEGER NOT NULL, - "difficulty_name" TEXT NOT NULL, - "max_combo" INTEGER NOT NULL, - "aim_difficulty" REAL NOT NULL, - "approach_rate" REAL NOT NULL, - "flashlight_difficulty" REAL NOT NULL, - "overall_difficulty" REAL NOT NULL, - "slider_factor" REAL NOT NULL, - "speed_difficulty" REAL NOT NULL, - "bpm" REAL NOT NULL, - "count_circles" INTEGER NOT NULL, - "count_sliders" INTEGER NOT NULL, - "count_spinners" INTEGER NOT NULL, - "circle_size" REAL NOT NULL, - "hp_drain" REAL NOT NULL, - "hit_length" INTEGER NOT NULL, - "last_updated" DATETIME NOT NULL, - "url" TEXT NOT NULL, - "artist" TEXT NOT NULL, - "artist_unicode" TEXT NOT NULL, - "cover_url" TEXT NOT NULL, - "cover_2x_url" TEXT NOT NULL, - "card_url" TEXT NOT NULL, - "card_2x_url" TEXT NOT NULL, - "list_url" TEXT NOT NULL, - "list_2x_url" TEXT NOT NULL, - "slim_cover_url" TEXT NOT NULL, - "slim_cover_2x_url" TEXT NOT NULL, - "preview_url" TEXT NOT NULL, - "title" TEXT NOT NULL, - "title_unicode" TEXT NOT NULL, - "set_mapper_user_id" INTEGER NOT NULL, - "available" BOOLEAN NOT NULL, - "fetch_time" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); -DROP TABLE "Map"; -ALTER TABLE "new_Map" RENAME TO "Map"; -CREATE TABLE "new_UserSession" ( - "id" TEXT NOT NULL PRIMARY KEY, - "osu_id" INTEGER NOT NULL, - "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "last_used" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "device" TEXT, - "browser" TEXT, - "os" TEXT, - CONSTRAINT "UserSession_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_UserSession" ("osu_id", "created_at", "last_used", "browser", "device", "id", "os") SELECT "osuId", "createdAt", "lastUsed", "browser", "device", "id", "os" FROM "UserSession"; -DROP TABLE "UserSession"; -ALTER TABLE "new_UserSession" RENAME TO "UserSession"; -CREATE TABLE "new_Team" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL, - "icon_url" TEXT NOT NULL, - "color" TEXT NOT NULL, - "tournament_id" INTEGER NOT NULL, - "scrim" BOOLEAN NOT NULL DEFAULT false, - CONSTRAINT "Team_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_Team" ("color", "icon_url", "id", "name", "scrim", "tournament_id") SELECT "color", "icon_url", "id", "name", "scrim", "tournamentId" FROM "Team"; -DROP TABLE "Team"; -ALTER TABLE "new_Team" RENAME TO "Team"; -CREATE TABLE "new_UserWithCustomBadge" ( - "user_id" INTEGER NOT NULL, - "badge_id" INTEGER NOT NULL, - - PRIMARY KEY ("user_id", "badge_id"), - CONSTRAINT "UserWithCustomBadge_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserWithCustomBadge_badge_id_fkey" FOREIGN KEY ("badge_id") REFERENCES "CustomBadge" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_UserWithCustomBadge" ("user_id", "badge_id") SELECT "userId", "badgeId" FROM "UserWithCustomBadge"; -DROP TABLE "UserWithCustomBadge"; -ALTER TABLE "new_UserWithCustomBadge" RENAME TO "UserWithCustomBadge"; -CREATE TABLE "new_UserWithOsuBadge" ( - "user_id" INTEGER NOT NULL, - "badge_id" INTEGER NOT NULL, - - PRIMARY KEY ("user_id", "badge_id"), - CONSTRAINT "UserWithOsuBadge_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserWithOsuBadge_badge_id_fkey" FOREIGN KEY ("badge_id") REFERENCES "OsuBadge" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_UserWithOsuBadge" ("user_id", "badge_id") SELECT "userId", "badgeId" FROM "UserWithOsuBadge"; -DROP TABLE "UserWithOsuBadge"; -ALTER TABLE "new_UserWithOsuBadge" RENAME TO "UserWithOsuBadge"; -CREATE TABLE "new_Round" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "is_qualifier" BOOLEAN NOT NULL DEFAULT false, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - "delete_warning" TEXT, - "tournament_id" INTEGER NOT NULL, - CONSTRAINT "Round_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_Round" ("acronym", "bans", "best_of", "delete_warning", "id", "name", "tournament_id") SELECT "acronym", "bans", "best_of", "delete_warning", "id", "name", "tournamentId" FROM "Round"; -DROP TABLE "Round"; -ALTER TABLE "new_Round" RENAME TO "Round"; -CREATE TABLE "new_UsersHostingTournament" ( - "user_id" INTEGER NOT NULL, - "tournament_id" INTEGER NOT NULL, - - PRIMARY KEY ("user_id", "tournament_id"), - CONSTRAINT "UsersHostingTournament_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "UsersHostingTournament_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UsersHostingTournament" ("user_id", "tournament_id") SELECT "userId", "tourney" FROM "UsersHostingTournament"; -DROP TABLE "UsersHostingTournament"; -ALTER TABLE "new_UsersHostingTournament" RENAME TO "UsersHostingTournament"; -CREATE TABLE "new_MapInPool" ( - "identifier" TEXT NOT NULL, - "mods" TEXT NOT NULL, - "map_id" INTEGER, - "mod_priority" INTEGER NOT NULL DEFAULT 0, - "mappool_id" INTEGER NOT NULL, - - PRIMARY KEY ("identifier", "mappool_id"), - CONSTRAINT "MapInPool_map_id_fkey" FOREIGN KEY ("map_id") REFERENCES "Map" ("id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "MapInPool_mappool_id_fkey" FOREIGN KEY ("mappool_id") REFERENCES "Mappool" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_MapInPool" ("identifier", "mods", "map_id", "mod_priority", "mappool_id") SELECT "identifier", "mods", "mapId", "modPriority", "mappoolId" FROM "MapInPool"; -DROP TABLE "MapInPool"; -ALTER TABLE "new_MapInPool" RENAME TO "MapInPool"; -CREATE TABLE "new_TeamInQualifierMatch" ( - "team_id" INTEGER NOT NULL, - "match_id" INTEGER NOT NULL, - - PRIMARY KEY ("team_id", "match_id"), - CONSTRAINT "TeamInQualifierMatch_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamInQualifierMatch_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "QualifierMatch" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -DROP TABLE "TeamInQualifierMatch"; -ALTER TABLE "new_TeamInQualifierMatch" RENAME TO "TeamInQualifierMatch"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; - --- CreateIndex -CREATE UNIQUE INDEX "_MappoolToRound_AB_unique" ON "_MappoolToRound"("A", "B"); - --- CreateIndex -CREATE INDEX "_MappoolToRound_B_index" ON "_MappoolToRound"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_MapToMappool_AB_unique" ON "_MapToMappool"("A", "B"); - --- CreateIndex -CREATE INDEX "_MapToMappool_B_index" ON "_MapToMappool"("B"); diff --git a/prisma/migrations/20231220001634_move_settings/migration.sql b/prisma/migrations/20231220001634_move_settings/migration.sql deleted file mode 100644 index e2c0a41..0000000 --- a/prisma/migrations/20231220001634_move_settings/migration.sql +++ /dev/null @@ -1,285 +0,0 @@ -/* - Warnings: - - - You are about to drop the `AutoHostRotate` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `AutoHostRotatePlayer` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `CustomBadge` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `MappoolInRound` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `ScrimSettings` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `UserWithCustomBadge` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `UserWithOsuBadge` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `UsersHostingTournament` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `_MapToMappool` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropIndex -DROP INDEX "AutoHostRotate_current_host_id_key"; - --- DropIndex -DROP INDEX "_MapToMappool_B_index"; - --- DropIndex -DROP INDEX "_MapToMappool_AB_unique"; - --- AlterTable -ALTER TABLE "Map" ADD COLUMN "star_rating_dt" REAL; -ALTER TABLE "Map" ADD COLUMN "star_rating_ez" REAL; -ALTER TABLE "Map" ADD COLUMN "star_rating_hr" REAL; -ALTER TABLE "Map" ADD COLUMN "star_rating_ht" REAL; - --- AlterTable -ALTER TABLE "MapInPool" ADD COLUMN "map_order" INTEGER; - --- AlterTable -ALTER TABLE "Team" ADD COLUMN "timezone" INTEGER; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "AutoHostRotate"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "AutoHostRotatePlayer"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "CustomBadge"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "MappoolInRound"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "ScrimSettings"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "UserWithCustomBadge"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "UserWithOsuBadge"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "UsersHostingTournament"; -PRAGMA foreign_keys=on; - --- DropTable -PRAGMA foreign_keys=off; -DROP TABLE "_MapToMappool"; -PRAGMA foreign_keys=on; - --- CreateTable -CREATE TABLE "UserTitle" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "awarded_at" DATETIME NOT NULL, - "name" TEXT NOT NULL, - "description" TEXT NOT NULL, - "image_url" TEXT NOT NULL, - "url" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "TournamentSettings" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "force_nf" BOOLEAN NOT NULL, - "score_mode" INTEGER NOT NULL, - "team_mode" INTEGER NOT NULL, - "team_size" INTEGER NOT NULL, - "x_v_x_mode" INTEGER NOT NULL, - "fm_mods" INTEGER NOT NULL DEFAULT 1, - "double_pick" INTEGER NOT NULL DEFAULT 1, - "double_ban" INTEGER NOT NULL DEFAULT 1, - "tournament_id" INTEGER, - "match_id" INTEGER, - CONSTRAINT "TournamentSettings_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TournamentSettings_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "TournamentSettings" ("force_nf", "score_mode", "team_mode", "team_size", "x_v_x_mode", "fm_mods", "double_pick", "double_ban", "tournament_id") SELECT "force_nf", "score_mode", "team_mode", "team_size", "x_v_x_mode", "fm_mods", "double_pick", "double_ban", "id" FROM "Tournament"; - --- CreateTable -CREATE TABLE "RoundSettings" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - "protects" INTEGER NOT NULL DEFAULT 0, - "round_id" INTEGER, - "match_id" INTEGER, - CONSTRAINT "RoundSettings_round_id_fkey" FOREIGN KEY ("round_id") REFERENCES "Round" ("id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "RoundSettings_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "RoundSettings" ("bans", "best_of", "round_id") SELECT "bans", "best_of", "id" FROM "Round"; - --- CreateTable -CREATE TABLE "Score" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "score" REAL NOT NULL, - "map_identifier" TEXT NOT NULL, - "match_id" INTEGER NOT NULL, - "user_id" INTEGER NOT NULL, - CONSTRAINT "Score_map_identifier_match_id_fkey" FOREIGN KEY ("map_identifier", "match_id") REFERENCES "MapInMatch" ("map_identifier", "match_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "Score_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "TeamScore" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "score" REAL NOT NULL, - "map_identifier" TEXT NOT NULL, - "match_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - CONSTRAINT "TeamScore_map_identifier_match_id_fkey" FOREIGN KEY ("map_identifier", "match_id") REFERENCES "MapInMatch" ("map_identifier", "match_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamScore_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "MappoolInMatch" ( - "mappool_id" INTEGER NOT NULL, - "match_id" INTEGER NOT NULL, - - PRIMARY KEY ("mappool_id", "match_id"), - CONSTRAINT "MappoolInMatch_mappool_id_fkey" FOREIGN KEY ("mappool_id") REFERENCES "Mappool" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MappoolInMatch_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "_OsuBadgeToUser" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL, - CONSTRAINT "_OsuBadgeToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "OsuBadge" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "_OsuBadgeToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "_UserToUserTitle" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL, - CONSTRAINT "_UserToUserTitle_A_fkey" FOREIGN KEY ("A") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "_UserToUserTitle_B_fkey" FOREIGN KEY ("B") REFERENCES "UserTitle" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "_TournamentToUser" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL, - CONSTRAINT "_TournamentToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "_TournamentToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_UserInTeam" ( - "osu_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - "member_order" INTEGER NOT NULL DEFAULT 0, - - PRIMARY KEY ("osu_id", "team_id"), - CONSTRAINT "UserInTeam_osu_id_fkey" FOREIGN KEY ("osu_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "UserInTeam_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UserInTeam" ("member_order", "osu_id", "team_id") SELECT "member_order", "osu_id", "team_id" FROM "UserInTeam"; -DROP TABLE "UserInTeam"; -ALTER TABLE "new_UserInTeam" RENAME TO "UserInTeam"; -CREATE TABLE "new_MapInMatch" ( - "match_id" INTEGER NOT NULL, - "map_identifier" TEXT NOT NULL, - "pool_id" INTEGER NOT NULL, - "protected_by_id" INTEGER, - "banned_by_id" INTEGER, - "picked_by_id" INTEGER, - "pick_number" INTEGER, - "pick_team_number" INTEGER, - "won_by_id" INTEGER, - "qualifier_id" INTEGER, - - PRIMARY KEY ("map_identifier", "match_id"), - CONSTRAINT "MapInMatch_map_identifier_pool_id_fkey" FOREIGN KEY ("map_identifier", "pool_id") REFERENCES "MapInPool" ("identifier", "mappool_id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_protected_by_id_fkey" FOREIGN KEY ("match_id", "protected_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_banned_by_id_fkey" FOREIGN KEY ("match_id", "banned_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_picked_by_id_fkey" FOREIGN KEY ("match_id", "picked_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_match_id_won_by_id_fkey" FOREIGN KEY ("match_id", "won_by_id") REFERENCES "TeamInMatch" ("match_id", "team_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "MapInMatch_qualifier_id_fkey" FOREIGN KEY ("qualifier_id") REFERENCES "QualifierMatch" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_MapInMatch" ("banned_by_id", "map_identifier", "match_id", "pick_number", "pick_team_number", "picked_by_id", "pool_id", "won_by_id") SELECT "banned_by_id", "map_identifier", "match_id", "pick_number", "pick_team_number", "picked_by_id", "pool_id", "won_by_id" FROM "MapInMatch"; -DROP TABLE "MapInMatch"; -ALTER TABLE "new_MapInMatch" RENAME TO "MapInMatch"; -CREATE TABLE "new_Mappool" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL, - "description" TEXT, - "public" BOOLEAN NOT NULL DEFAULT false -); -INSERT INTO "new_Mappool" ("description", "id", "name", "public") SELECT "description", "id", "name", "public" FROM "Mappool"; -DROP TABLE "Mappool"; -ALTER TABLE "new_Mappool" RENAME TO "Mappool"; -CREATE TABLE "new_Round" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "is_qualifier" BOOLEAN NOT NULL DEFAULT false, - "tournament_id" INTEGER NOT NULL, - CONSTRAINT "Round_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_Round" ("acronym", "id", "is_qualifier", "name", "tournament_id") SELECT "acronym", "id", "is_qualifier", "name", "tournament_id" FROM "Round"; -DROP TABLE "Round"; -ALTER TABLE "new_Round" RENAME TO "Round"; -CREATE TABLE "new_Tournament" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "acronym" TEXT NOT NULL, - "name" TEXT NOT NULL, - "color" TEXT NOT NULL, - "banner_url" TEXT NOT NULL, - "description" TEXT NOT NULL, - "icon_url" TEXT NOT NULL, - "allow_registrations" BOOLEAN NOT NULL, - "guild_id" TEXT, - "private" BOOLEAN NOT NULL DEFAULT false, - "twitch_account_id" INTEGER, - CONSTRAINT "Tournament_guild_id_fkey" FOREIGN KEY ("guild_id") REFERENCES "Guild" ("guild_id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "Tournament_twitch_account_id_fkey" FOREIGN KEY ("twitch_account_id") REFERENCES "TwitchAccount" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_Tournament" ("acronym", "allow_registrations", "banner_url", "color", "description", "guild_id", "icon_url", "id", "name", "private", "twitch_account_id") SELECT "acronym", "allow_registrations", "banner_url", "color", "description", "guild_id", "icon_url", "id", "name", "private", "twitch_account_id" FROM "Tournament"; -DROP TABLE "Tournament"; -ALTER TABLE "new_Tournament" RENAME TO "Tournament"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; - --- CreateIndex -CREATE UNIQUE INDEX "TournamentSettings_tournament_id_key" ON "TournamentSettings"("tournament_id"); - --- CreateIndex -CREATE UNIQUE INDEX "TournamentSettings_match_id_key" ON "TournamentSettings"("match_id"); - --- CreateIndex -CREATE UNIQUE INDEX "RoundSettings_round_id_key" ON "RoundSettings"("round_id"); - --- CreateIndex -CREATE UNIQUE INDEX "RoundSettings_match_id_key" ON "RoundSettings"("match_id"); - --- CreateIndex -CREATE UNIQUE INDEX "_OsuBadgeToUser_AB_unique" ON "_OsuBadgeToUser"("A", "B"); - --- CreateIndex -CREATE INDEX "_OsuBadgeToUser_B_index" ON "_OsuBadgeToUser"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_UserToUserTitle_AB_unique" ON "_UserToUserTitle"("A", "B"); - --- CreateIndex -CREATE INDEX "_UserToUserTitle_B_index" ON "_UserToUserTitle"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_TournamentToUser_AB_unique" ON "_TournamentToUser"("A", "B"); - --- CreateIndex -CREATE INDEX "_TournamentToUser_B_index" ON "_TournamentToUser"("B"); diff --git a/prisma/migrations/20231220005120_score_improvements/migration.sql b/prisma/migrations/20231220005120_score_improvements/migration.sql deleted file mode 100644 index 7268da8..0000000 --- a/prisma/migrations/20231220005120_score_improvements/migration.sql +++ /dev/null @@ -1,67 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_Score" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "score" REAL NOT NULL, - "mods" TEXT NOT NULL DEFAULT '', - "map_identifier" TEXT NOT NULL, - "match_id" INTEGER NOT NULL, - "user_id" INTEGER NOT NULL, - "team_score_id" INTEGER, - CONSTRAINT "Score_map_identifier_match_id_fkey" FOREIGN KEY ("map_identifier", "match_id") REFERENCES "MapInMatch" ("map_identifier", "match_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "Score_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "Score_team_score_id_fkey" FOREIGN KEY ("team_score_id") REFERENCES "TeamScore" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_Score" ("id", "map_identifier", "match_id", "score", "user_id") SELECT "id", "map_identifier", "match_id", "score", "user_id" FROM "Score"; -DROP TABLE "Score"; -ALTER TABLE "new_Score" RENAME TO "Score"; -CREATE TABLE "new_TournamentSettings" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "force_nf" BOOLEAN NOT NULL, - "score_mode" INTEGER NOT NULL, - "team_mode" INTEGER NOT NULL, - "team_size" INTEGER NOT NULL, - "x_v_x_mode" INTEGER NOT NULL, - "fm_mods" INTEGER NOT NULL DEFAULT 1, - "double_pick" INTEGER NOT NULL DEFAULT 1, - "double_ban" INTEGER NOT NULL DEFAULT 1, - "tournament_id" INTEGER, - "match_id" INTEGER, - CONSTRAINT "TournamentSettings_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament" ("id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "TournamentSettings_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_TournamentSettings" ("double_ban", "double_pick", "fm_mods", "force_nf", "id", "match_id", "score_mode", "team_mode", "team_size", "tournament_id", "x_v_x_mode") SELECT "double_ban", "double_pick", "fm_mods", "force_nf", "id", "match_id", "score_mode", "team_mode", "team_size", "tournament_id", "x_v_x_mode" FROM "TournamentSettings"; -DROP TABLE "TournamentSettings"; -ALTER TABLE "new_TournamentSettings" RENAME TO "TournamentSettings"; -CREATE UNIQUE INDEX "TournamentSettings_tournament_id_key" ON "TournamentSettings"("tournament_id"); -CREATE UNIQUE INDEX "TournamentSettings_match_id_key" ON "TournamentSettings"("match_id"); -CREATE TABLE "new_TeamScore" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "score" REAL NOT NULL, - "freemod" BOOLEAN NOT NULL DEFAULT false, - "map_identifier" TEXT NOT NULL, - "match_id" INTEGER NOT NULL, - "team_id" INTEGER NOT NULL, - CONSTRAINT "TeamScore_map_identifier_match_id_fkey" FOREIGN KEY ("map_identifier", "match_id") REFERENCES "MapInMatch" ("map_identifier", "match_id") ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT "TeamScore_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "Team" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); -INSERT INTO "new_TeamScore" ("id", "map_identifier", "match_id", "score", "team_id") SELECT "id", "map_identifier", "match_id", "score", "team_id" FROM "TeamScore"; -DROP TABLE "TeamScore"; -ALTER TABLE "new_TeamScore" RENAME TO "TeamScore"; -CREATE TABLE "new_RoundSettings" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "bans" INTEGER NOT NULL, - "best_of" INTEGER NOT NULL, - "protects" INTEGER NOT NULL, - "round_id" INTEGER, - "match_id" INTEGER, - CONSTRAINT "RoundSettings_round_id_fkey" FOREIGN KEY ("round_id") REFERENCES "Round" ("id") ON DELETE SET NULL ON UPDATE CASCADE, - CONSTRAINT "RoundSettings_match_id_fkey" FOREIGN KEY ("match_id") REFERENCES "Match" ("id") ON DELETE SET NULL ON UPDATE CASCADE -); -INSERT INTO "new_RoundSettings" ("bans", "best_of", "id", "match_id", "protects", "round_id") SELECT "bans", "best_of", "id", "match_id", "protects", "round_id" FROM "RoundSettings"; -DROP TABLE "RoundSettings"; -ALTER TABLE "new_RoundSettings" RENAME TO "RoundSettings"; -CREATE UNIQUE INDEX "RoundSettings_round_id_key" ON "RoundSettings"("round_id"); -CREATE UNIQUE INDEX "RoundSettings_match_id_key" ON "RoundSettings"("match_id"); -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml deleted file mode 100644 index e5e5c47..0000000 --- a/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "sqlite" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma deleted file mode 100644 index 4ae3f75..0000000 --- a/prisma/schema.prisma +++ /dev/null @@ -1,327 +0,0 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -generator client { - provider = "prisma-client-js" - binaryTargets = ["native", "linux-musl"] -} - -generator dbml { - provider = "prisma-dbml-generator" -} - -datasource db { - provider = "sqlite" - url = env("DATABASE_URL") -} - -model User { - id Int @id - username String - country_code String - country_name String - cover_url String - ranked_score BigInt - play_count Int - total_score BigInt - pp_rank Int - level Int - level_progress Int - hit_accuracy Float - pp Float - - osu_token OsuOauth? - in_teams UserInTeam[] - host_of Tournament[] - invites TeamInvite[] - scores Score[] -} - -model OsuOauth { - user_id Int @id - last_update DateTime @default(now()) - access_token String - expires_in Int - refresh_token String - token_type String - - user User @relation(fields: [user_id], references: [id]) -} - -model Tournament { - id Int @id @default(autoincrement()) - acronym String - name String - color String - banner_url String - description String - icon_url String - allow_registrations Boolean - rounds Round[] - guild_id String? - private Boolean @default(false) - teams Team[] - - hosts User[] - settings TournamentSettings? - ModMultiplier ModMultiplier[] -} - -// A model that holds the tournament's settings required to run a match. -// These settings exist inside it's own model so that a match can -// be run without instantiating a full tournament object. -model TournamentSettings { - id Int @id @default(autoincrement()) - - gamemode Int @default(0) // 0: std, 1: taiko, 2: catch, 3: mania - - force_nf Boolean - score_mode Int - team_mode Int - team_size Int - x_v_x_mode Int - fm_mods Int @default(1) // How many mods are required for freemod picks - double_pick Int @default(1) // 0: No double picking; 1: Only double picking NM; 2 Double picking allowed - double_ban Int @default(1) // 0: No double banning; 1: Only double banning NM; 2 Double banning allowed - mod_multipliers ModMultiplier[] - - for_tournament Tournament? @relation(fields: [tournament_id], references: [id]) - tournament_id Int? @unique - for_match Match? @relation(fields: [match_id], references: [id]) - match_id Int? @unique - MapInPool MapInPool[] -} - -model ModMultiplier { - id Int @id @default(autoincrement()) - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int - mod_string String - match_exactly Boolean @default(false) - multiplier Float - settings_for TournamentSettings[] -} - -model Round { - id Int @id @default(autoincrement()) - acronym String - name String - matches Match[] - tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) - tournament_id Int - mappools MappoolInRound[] -} - -model MappoolInRound { - mappool Mappool @relation(fields: [mappool_id], references: [id]) - round Round @relation(fields: [round_id], references: [id]) - mappool_id Int - round_id Int - - @@id([mappool_id, round_id]) -} - -model Mappool { - id Int @id @default(autoincrement()) - name String - map_in_pools MapInPool[] - public Boolean @default(false) - - in_rounds MappoolInRound[] - in_matches MappoolInMatch[] -} - -model TeamInvite { - invitee_user_id Int - invitee User @relation(fields: [invitee_user_id], references: [id]) - team_id Int - team Team @relation(fields: [team_id], references: [id], onDelete: Cascade) - - @@id([invitee_user_id, team_id]) -} - -model MapInPool { - identifier String // NM1, NM2 etc. - mods String - data Map? @relation(fields: [map_id], references: [id]) - map_id Int? - map_order Int? - mappool Mappool @relation(fields: [mappool_id], references: [id], onDelete: Cascade) - mappool_id Int - used_in MatchBlock[] - settings TournamentSettings? @relation(fields: [tournamentSettingsId], references: [id]) - tournamentSettingsId Int? - - @@id([identifier, mappool_id]) -} - -// New and improved and now based on osu!api v2 -// osu!standard only -model Map { - // Beatmap attributes - id Int @id - beatmapset_id Int - - title String - artist String - difficulty_name String //'version' - - // Web display properties - url String - cover_url String //'cover.slimcover@2x' - status String - total_length Int - max_combo Int - bpm Float - last_updated DateTime - - cs Float - ar Float - od Float - hp Float - - star_rating Float //'difficulty_rating' - // Fetched when needed - star_rating_dt Float? - star_rating_hr Float? - star_rating_ez Float? - star_rating_ht Float? - - // Whether a user is able to download using - // osu!direct/official servers - available Boolean - - // Other - fetch_time DateTime @default(now()) - in_pools MapInPool[] -} - -model Team { - id Int @id @default(autoincrement()) - name String - icon_url String - color String - members UserInTeam[] - tournament Tournament @relation(fields: [tournament_id], references: [id], onDelete: Cascade) - tournament_id Int - timezone Int? // UTC Offset - in_matches TeamInMatch[] - invited_users TeamInvite[] - scores TeamScore[] -} - -model UserInTeam { - osu_id Int - user User @relation(fields: [osu_id], references: [id]) - team Team @relation(fields: [team_id], references: [id], onDelete: Cascade) - team_id Int - member_order Int @default(0) - - @@id([osu_id, team_id]) -} - -model Match { - id Int @id @default(autoincrement()) - teams TeamInMatch[] - start_time DateTime? - mp_link String? - round Round? @relation(fields: [round_id], references: [id]) - round_id Int? - - waiting_on Int? // ID of the team in match, who's turn is it - sections BlockSection[] - current_section Int // ID of current block section - block_in_section Int // ID of block - - scrim Boolean @default(false) - tournament_settings TournamentSettings? - mappools MappoolInMatch[] -} - -model BlockSection { - id Int @id @default(autoincrement()) - - match Match @relation(fields: [match_id], references: [id]) - match_id Int - - action String - blocks MatchBlock[] - - @@unique([id, action]) -} - -model MatchBlock { - id Int @id @default(autoincrement()) - - section BlockSection @relation(fields: [section_id, action], references: [id, action]) - section_id Int - action String - - // Link a map - map MapInPool? @relation(fields: [map_identifier, pool_id], references: [identifier, mappool_id]) - map_identifier String? - pool_id Int? - - acted_on_by TeamInMatch? @relation(fields: [acted_on_by_id], references: [id]) - acted_on_by_id Int - - scores Score[] - team_scores TeamScore[] -} - -model TeamInMatch { - id Int @id @default(autoincrement()) - - match_id Int - team_id Int? - match Match @relation(fields: [match_id], references: [id], onDelete: Cascade) - team Team? @relation(fields: [team_id], references: [id]) - score Int - roll Int? - aborts Int @default(0) - faults Int @default(0) - - actions MatchBlock[] - - winner Boolean? -} - -model Score { - id Int @id @default(autoincrement()) - - score Float - mods String @default("") - - block MatchBlock @relation(fields: [block_id], references: [id]) - block_id Int - - user User @relation(fields: [user_id], references: [id]) - user_id Int - - scores_for TeamScore? @relation(fields: [team_score_id], references: [id]) - team_score_id Int? -} - -model TeamScore { - id Int @id @default(autoincrement()) - - score Float - freemod Boolean @default(false) - - block MatchBlock @relation(fields: [block_id], references: [id]) - block_id Int - - team Team @relation(fields: [team_id], references: [id]) - team_id Int - - player_scores Score[] -} - -model MappoolInMatch { - mappool Mappool @relation(fields: [mappool_id], references: [id]) - match Match @relation(fields: [match_id], references: [id]) - mappool_id Int - match_id Int - - @@id([mappool_id, match_id]) -} diff --git a/src/index.ts b/src/index.ts index efe44bf..66628f1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,26 @@ -import { Elysia } from 'elysia'; -import { rest } from './rest'; -import { websocket } from './ws'; -const { PORT } = Bun.env; +import { buildSchema } from "drizzle-graphql"; +import { drizzle } from "drizzle-orm/libsql" +import express from "express"; +import { graphqlHTTP } from "express-graphql"; +import { ruruHTML } from "ruru/server"; +import { createClient } from "@libsql/client"; +import * as dbSchema from "./lib/drizzle/schema"; -if (!PORT) { - throw 'No PORT Specified in env variables!'; -} +const app = express(); -const app = new Elysia().use(rest).use(websocket).listen(PORT); +const client = createClient({ url: "file:../yagami-db/dev.db" }) +const db = drizzle(client, { "schema": dbSchema }); -console.log(`Running API at ${app.server?.hostname}:${app.server?.port}`); +const { schema } = buildSchema(db); + +app.all( + "/graphql", + graphqlHTTP({ schema }) +).get( + "/", (_req, res) => { + res.type("html"); + res.end(ruruHTML({ endpoint: "/graphql" })) + } +).listen(5173, () => { + console.log("server up") +}) \ No newline at end of file diff --git a/src/prisma.ts b/src/prisma.ts deleted file mode 100644 index 0a7fbaa..0000000 --- a/src/prisma.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -export const prisma = new PrismaClient(); diff --git a/src/rest/docs/index.ts b/src/rest/docs/index.ts deleted file mode 100644 index 8e2c888..0000000 --- a/src/rest/docs/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import swagger from '@elysiajs/swagger'; - -export default swagger({ - exclude: ['/'], - documentation: { - tags: [{ name: 'Tournaments' }], - info: { - title: 'Yagami API Documentation', - version: '1.0.0', - description: 'The RESTFUL-facing API that allows you to interact with the Yagami Database', - contact: { - name: 'clxxiii', - url: 'https://yagami.app', - email: 'info@yagami.app', - }, - }, - }, -}); diff --git a/src/rest/index.ts b/src/rest/index.ts deleted file mode 100644 index 9284305..0000000 --- a/src/rest/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Elysia from 'elysia'; -import { tournament } from './tournament'; -import swagger from './docs'; - -const { DOCS_URL } = process.env; - -export const rest = new Elysia() - .use(swagger) - .use(tournament) - .get('/', ({ set }) => (set.redirect = DOCS_URL), {}); diff --git a/src/rest/tournament/get.ts b/src/rest/tournament/get.ts deleted file mode 100644 index 220d7d6..0000000 --- a/src/rest/tournament/get.ts +++ /dev/null @@ -1,76 +0,0 @@ -import Elysia from 'elysia'; -import { prisma } from '../../prisma'; -import { LocalHook } from 'elysia'; - -const hooks: LocalHook = { - beforeHandle: ({ params: { id }, set }) => { - if (isNaN(parseInt(id))) { - set.status = 'Bad Request'; - return { - error: 'Tournament ID is not a number', - }; - } - }, - detail: { - tags: ['Tournaments'], - }, -}; - -export const get = new Elysia() - .get('/:id/get_partial', ({ params }) => getPartial(params.id), hooks) - .get('/:id/get_full', ({ params }) => getFull(params.id), hooks); - -const getPartial = async (id: string) => { - const tournament = await prisma.tournament.findUnique({ - where: { - id: parseInt(id), - }, - }); - return tournament; -}; - -const getFull = async (id: string) => { - const tournament = await prisma.tournament.findUnique({ - where: { - id: parseInt(id), - }, - include: { - Hosts: { - select: { - User: { - select: { - id: true, - username: true, - }, - }, - }, - }, - rounds: { - include: { - Match: { - include: { - MapsInMatch: true, - Teams: { - include: { - Team: true, - }, - }, - }, - }, - mappool: { - include: { - Maps: { - select: { - mods: true, - identifier: true, - mapId: true, - }, - }, - }, - }, - }, - }, - }, - }); - return tournament; -}; diff --git a/src/rest/tournament/index.ts b/src/rest/tournament/index.ts deleted file mode 100644 index 831f8e1..0000000 --- a/src/rest/tournament/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Elysia } from 'elysia'; -import { get } from './get'; - -export const tournament = new Elysia({ prefix: '/tournaments' }).use(get); diff --git a/src/ws/index.ts b/src/ws/index.ts deleted file mode 100644 index 23bf3e9..0000000 --- a/src/ws/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import Elysia from 'elysia'; - -export const websocket = new Elysia().ws('/ws', { - message: (ws, message) => {}, -}); From b5c02653efccce66d25c663ffddf34e958b87b5e Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sat, 1 Jun 2024 23:30:04 -0400 Subject: [PATCH 06/11] dead-simple api with graphql dep --- bun.lockb | Bin 135593 -> 133518 bytes package.json | 2 +- src/graphql.ts | 9 +++++++++ src/index.ts | 25 ++++++++++++------------- src/lib/drizzle/index.ts | 8 ++++++++ 5 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 src/graphql.ts create mode 100644 src/lib/drizzle/index.ts diff --git a/bun.lockb b/bun.lockb index 80c16ba9fd74956687ee440e4d21d245e65b9208..51342a0b16fa2604b353708a2d0028595f404506 100755 GIT binary patch delta 24495 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 VH^9*Co3^mmt8D+^0Q;f)e*vEoCma9( delta 25638 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 YD)`?J&@=s~2y=gDO|~rF&Thy2KayL@C;$Ke diff --git a/package.json b/package.json index 7fee1a7..2e79091 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "drizzle-graphql": "^0.8.2", "drizzle-orm": "^0.31.0", "express": "^4.18.2", - "express-graphql": "^0.12.0", "express-ws": "^5.0.2", + "graphql": "^16.8.1", "ruru": "^2.0.0-beta.11" } } diff --git a/src/graphql.ts b/src/graphql.ts new file mode 100644 index 0000000..986a15a --- /dev/null +++ b/src/graphql.ts @@ -0,0 +1,9 @@ +import { db } from "./lib/drizzle" +import { buildSchema } from "drizzle-graphql" +import { graphql } from "graphql" + +const { schema } = buildSchema(db); + +export const sendQuery = (query: string) => { + return graphql({ schema, source: query }) +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 66628f1..67a9364 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,20 @@ -import { buildSchema } from "drizzle-graphql"; -import { drizzle } from "drizzle-orm/libsql" import express from "express"; -import { graphqlHTTP } from "express-graphql"; import { ruruHTML } from "ruru/server"; -import { createClient } from "@libsql/client"; -import * as dbSchema from "./lib/drizzle/schema"; +import { sendQuery } from "./graphql" const app = express(); -const client = createClient({ url: "file:../yagami-db/dev.db" }) -const db = drizzle(client, { "schema": dbSchema }); - -const { schema } = buildSchema(db); - -app.all( - "/graphql", - graphqlHTTP({ schema }) +app.use(express.json()) +app.post( + "/graphql", (req, res) => { + console.log(req.body); + const request = req.body; + const query = request.query + sendQuery(query).then(response => { + res.send(JSON.stringify(response)) + } + ) + } ).get( "/", (_req, res) => { res.type("html"); diff --git a/src/lib/drizzle/index.ts b/src/lib/drizzle/index.ts new file mode 100644 index 0000000..5c048e7 --- /dev/null +++ b/src/lib/drizzle/index.ts @@ -0,0 +1,8 @@ +import { drizzle } from "drizzle-orm/libsql" +import { createClient } from "@libsql/client"; +import * as schema from "./schema" + +const client = createClient({ url: "file:../yagami-db/dev.db" }) +const db = drizzle(client, { schema }); + +export { schema, db } \ No newline at end of file From e54333c9b04add5fa1d9779b00ed7ca91106de17 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sun, 2 Jun 2024 00:23:12 -0400 Subject: [PATCH 07/11] add example of editing mutations --- src/graphql.ts | 29 +++++++++++++++++++++++++++-- src/index.ts | 1 - 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/graphql.ts b/src/graphql.ts index 986a15a..041cf73 100644 --- a/src/graphql.ts +++ b/src/graphql.ts @@ -1,9 +1,34 @@ import { db } from "./lib/drizzle" import { buildSchema } from "drizzle-graphql" -import { graphql } from "graphql" +import { GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, graphql } from "graphql" -const { schema } = buildSchema(db); +const { entities } = buildSchema(db); + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: entities.queries + }), + mutation: new GraphQLObjectType({ + name: 'Mutations', + fields: { + updateSettings: { + type: new GraphQLList(new GraphQLNonNull(entities.types.SettingsItem)), + args: { + set: { + type: new GraphQLNonNull(entities.inputs.SettingsUpdateInput), + }, + where: { + type: entities.inputs.SettingsFilters + } + }, + resolve: entities.mutations.updateSettings.resolve + }, + duplicate: entities.mutations.updateSettings + } + }) +}) export const sendQuery = (query: string) => { return graphql({ schema, source: query }) } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 67a9364..b7503a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ const app = express(); app.use(express.json()) app.post( "/graphql", (req, res) => { - console.log(req.body); const request = req.body; const query = request.query sendQuery(query).then(response => { From 3aaa773f1d0c2506dda790bf53690682cd4867ed Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sun, 2 Jun 2024 11:29:46 -0400 Subject: [PATCH 08/11] remove osu oauth token from schema --- drizzle.config.ts | 2 +- src/graphql.ts | 10 +++- ...rmin.sql => 0000_colorful_lady_vermin.sql} | 9 --- src/lib/drizzle/index.ts | 7 ++- src/lib/drizzle/meta/0000_snapshot.json | 60 +------------------ src/lib/drizzle/meta/_journal.json | 4 +- src/lib/drizzle/relations.ts | 17 +----- src/lib/drizzle/schema.ts | 15 ----- 8 files changed, 21 insertions(+), 103 deletions(-) rename src/lib/drizzle/{0000_wild_vermin.sql => 0000_colorful_lady_vermin.sql} (96%) diff --git a/drizzle.config.ts b/drizzle.config.ts index 408a956..0ee60de 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -4,7 +4,7 @@ import { defineConfig } from 'drizzle-kit'; export default defineConfig({ dialect: 'sqlite', out: './src/lib/drizzle', - schema: "./src/lib/drizzle/schema.ts", + schema: ["./src/lib/drizzle/schema.ts", "./src/lib/drizzle/relations.ts"], dbCredentials: { url: 'file:../yagami-db/dev.db' }, diff --git a/src/graphql.ts b/src/graphql.ts index 041cf73..d15c05e 100644 --- a/src/graphql.ts +++ b/src/graphql.ts @@ -8,7 +8,15 @@ const { entities } = buildSchema(db); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', - fields: entities.queries + fields: { + getMap: entities.queries.mapinpool, + getMappool: entities.queries.mappool, + getMatch: entities.queries.match, + getTeam: entities.queries.team, + getTournament: entities.queries.tournament, + getUser: entities.queries.user, + getSettings: entities.queries.settings + } }), mutation: new GraphQLObjectType({ name: 'Mutations', diff --git a/src/lib/drizzle/0000_wild_vermin.sql b/src/lib/drizzle/0000_colorful_lady_vermin.sql similarity index 96% rename from src/lib/drizzle/0000_wild_vermin.sql rename to src/lib/drizzle/0000_colorful_lady_vermin.sql index 8130c8b..d166af7 100644 --- a/src/lib/drizzle/0000_wild_vermin.sql +++ b/src/lib/drizzle/0000_colorful_lady_vermin.sql @@ -102,15 +102,6 @@ CREATE TABLE `ModMultiplier` ( FOREIGN KEY (`settings_id`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE cascade ); --> statement-breakpoint -CREATE TABLE `OsuOauth` ( - `user_id` integer PRIMARY KEY NOT NULL, - `token_type` text NOT NULL, - `access_token` text NOT NULL, - `refresh_token` text NOT NULL, - `expires_at` integer NOT NULL, - FOREIGN KEY (`user_id`) REFERENCES `User`(`id`) ON UPDATE cascade ON DELETE cascade -); ---> statement-breakpoint CREATE TABLE `Round` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `acronym` text NOT NULL, diff --git a/src/lib/drizzle/index.ts b/src/lib/drizzle/index.ts index 5c048e7..2469a3b 100644 --- a/src/lib/drizzle/index.ts +++ b/src/lib/drizzle/index.ts @@ -1,8 +1,11 @@ import { drizzle } from "drizzle-orm/libsql" import { createClient } from "@libsql/client"; import * as schema from "./schema" +import * as relations from "./relations" const client = createClient({ url: "file:../yagami-db/dev.db" }) -const db = drizzle(client, { schema }); -export { schema, db } \ No newline at end of file +const data = { ...schema, ...relations } +const db = drizzle(client, { schema: data }); + +export { data, db } \ No newline at end of file diff --git a/src/lib/drizzle/meta/0000_snapshot.json b/src/lib/drizzle/meta/0000_snapshot.json index d263ac6..fd9b9fb 100644 --- a/src/lib/drizzle/meta/0000_snapshot.json +++ b/src/lib/drizzle/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "6", "dialect": "sqlite", - "id": "ef9eedf8-f8b9-42e6-a743-12e6f3c63358", + "id": "4148f672-3831-434a-8c8b-0b0e174e0e98", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "BlockSection": { @@ -746,64 +746,6 @@ "compositePrimaryKeys": {}, "uniqueConstraints": {} }, - "OsuOauth": { - "name": "OsuOauth", - "columns": { - "user_id": { - "name": "user_id", - "type": "integer", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "token_type": { - "name": "token_type", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - } - }, - "indexes": {}, - "foreignKeys": { - "OsuOauth_user_id_User_id_fk": { - "name": "OsuOauth_user_id_User_id_fk", - "tableFrom": "OsuOauth", - "tableTo": "User", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, "Round": { "name": "Round", "columns": { diff --git a/src/lib/drizzle/meta/_journal.json b/src/lib/drizzle/meta/_journal.json index aaeab53..274e8d6 100644 --- a/src/lib/drizzle/meta/_journal.json +++ b/src/lib/drizzle/meta/_journal.json @@ -5,8 +5,8 @@ { "idx": 0, "version": "6", - "when": 1717292642551, - "tag": "0000_wild_vermin", + "when": 1717341832866, + "tag": "0000_colorful_lady_vermin", "breakpoints": true } ] diff --git a/src/lib/drizzle/relations.ts b/src/lib/drizzle/relations.ts index 33566c7..463df20 100644 --- a/src/lib/drizzle/relations.ts +++ b/src/lib/drizzle/relations.ts @@ -1,5 +1,5 @@ import { relations } from "drizzle-orm/relations"; -import { Match, Settings, Tournament, Round, MappoolInRound, Mappool, MapInPool, Map, User, OsuOauth, Team, UserInTeam, BlockSection, TeamInMatch, MatchBlock, TeamScore, Score, ModMultiplier, MapStats, TeamInTournament } from "./schema"; +import { Match, Settings, Tournament, Round, MappoolInRound, Mappool, MapInPool, Map, User, Team, UserInTeam, BlockSection, TeamInMatch, MatchBlock, TeamScore, Score, ModMultiplier, MapStats, TeamInTournament } from "./schema"; export const TournamentRelations = relations(Tournament, ({ one, many }) => ({ @@ -80,18 +80,7 @@ export const MapStatsRelations = relations(MapStats, ({ one }) => ({ }) })) -export const OsuOauthRelations = relations(OsuOauth, ({ one }) => ({ - user: one(User, { - fields: [OsuOauth.user_id], - references: [User.id] - }), -})); - -export const UserRelations = relations(User, ({ many, one }) => ({ - token: one(OsuOauth, { - fields: [User.id], - references: [OsuOauth.user_id] - }), +export const UserRelations = relations(User, ({ many }) => ({ in_teams_list: many(UserInTeam), scores: many(Score), })); @@ -144,7 +133,7 @@ export const MatchRelations = relations(Match, ({ one, many }) => ({ relationName: "current_section" }), current_block: one(MatchBlock, { - fields: [Match.current_block_id], + fields: [Match.block_in_section_id], references: [MatchBlock.id], relationName: "current_block" }) diff --git a/src/lib/drizzle/schema.ts b/src/lib/drizzle/schema.ts index d1fa5fa..e5b8c44 100644 --- a/src/lib/drizzle/schema.ts +++ b/src/lib/drizzle/schema.ts @@ -173,21 +173,6 @@ export const MapStats = sqliteTable('MapStats', { composite_key: primaryKey({ columns: [table.map_id, table.mod_string] }) })) -/** - * Contains a user's osu OauthV2 token. - * - * Used for updating player information, like rank &pp - */ -export const OsuOauth = sqliteTable("OsuOauth", { - user_id: integer("user_id").primaryKey().references(() => User.id, { onDelete: "cascade", onUpdate: "cascade" }), - - token_type: text("token_type").notNull(), // almost always "Bearer" - access_token: text("access_token").notNull(), - refresh_token: text("refresh_token").notNull(), - - expires_at: integer("expires_at", { mode: 'timestamp_ms' }).notNull() -}); - /** * Represents an osu user. * From 545c8d18bbeeef47a899bb96c0bb95c8a5a17d41 Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sun, 2 Jun 2024 12:24:23 -0400 Subject: [PATCH 09/11] fix some schema mistakes --- ...dy_vermin.sql => 0000_thin_vindicator.sql} | 13 +++--- src/lib/drizzle/meta/0000_snapshot.json | 43 +++++++++++-------- src/lib/drizzle/meta/_journal.json | 4 +- src/lib/drizzle/schema.ts | 6 +-- 4 files changed, 37 insertions(+), 29 deletions(-) rename src/lib/drizzle/{0000_colorful_lady_vermin.sql => 0000_thin_vindicator.sql} (95%) diff --git a/src/lib/drizzle/0000_colorful_lady_vermin.sql b/src/lib/drizzle/0000_thin_vindicator.sql similarity index 95% rename from src/lib/drizzle/0000_colorful_lady_vermin.sql rename to src/lib/drizzle/0000_thin_vindicator.sql index d166af7..9290091 100644 --- a/src/lib/drizzle/0000_colorful_lady_vermin.sql +++ b/src/lib/drizzle/0000_thin_vindicator.sql @@ -28,11 +28,11 @@ CREATE TABLE `MapInPool` ( `mods` text NOT NULL, `mappool_id` integer NOT NULL, `map_id` integer, - `tournamentSettingsId` integer, + `settings_id` integer, PRIMARY KEY(`identifier`, `mappool_id`), FOREIGN KEY (`mappool_id`) REFERENCES `Mappool`(`id`) ON UPDATE cascade ON DELETE cascade, FOREIGN KEY (`map_id`) REFERENCES `Map`(`id`) ON UPDATE cascade ON DELETE set null, - FOREIGN KEY (`tournamentSettingsId`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE set null + FOREIGN KEY (`settings_id`) REFERENCES `Settings`(`id`) ON UPDATE cascade ON DELETE set null ); --> statement-breakpoint CREATE TABLE `MapStats` ( @@ -158,10 +158,11 @@ CREATE TABLE `TeamInMatch` ( ); --> statement-breakpoint CREATE TABLE `TeamInTournament` ( - `id` integer, - PRIMARY KEY(`id`, `id`), - FOREIGN KEY (`id`) REFERENCES `Tournament`(`id`) ON UPDATE no action ON DELETE no action, - FOREIGN KEY (`id`) REFERENCES `Team`(`id`) ON UPDATE no action ON DELETE no action + `tournament_id` integer, + `team_id` integer, + PRIMARY KEY(`team_id`, `tournament_id`), + FOREIGN KEY (`tournament_id`) REFERENCES `Tournament`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`team_id`) REFERENCES `Team`(`id`) ON UPDATE no action ON DELETE no action ); --> statement-breakpoint CREATE TABLE `TeamScore` ( diff --git a/src/lib/drizzle/meta/0000_snapshot.json b/src/lib/drizzle/meta/0000_snapshot.json index fd9b9fb..53c9f08 100644 --- a/src/lib/drizzle/meta/0000_snapshot.json +++ b/src/lib/drizzle/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "6", "dialect": "sqlite", - "id": "4148f672-3831-434a-8c8b-0b0e174e0e98", + "id": "46120f16-3830-46fa-8d97-8670e1da5ef7", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "BlockSection": { @@ -200,8 +200,8 @@ "notNull": false, "autoincrement": false }, - "tournamentSettingsId": { - "name": "tournamentSettingsId", + "settings_id": { + "name": "settings_id", "type": "integer", "primaryKey": false, "notNull": false, @@ -236,12 +236,12 @@ "onDelete": "set null", "onUpdate": "cascade" }, - "MapInPool_tournamentSettingsId_Settings_id_fk": { - "name": "MapInPool_tournamentSettingsId_Settings_id_fk", + "MapInPool_settings_id_Settings_id_fk": { + "name": "MapInPool_settings_id_Settings_id_fk", "tableFrom": "MapInPool", "tableTo": "Settings", "columnsFrom": [ - "tournamentSettingsId" + "settings_id" ], "columnsTo": [ "id" @@ -1146,8 +1146,15 @@ "TeamInTournament": { "name": "TeamInTournament", "columns": { - "id": { - "name": "id", + "tournament_id": { + "name": "tournament_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "team_id": { + "name": "team_id", "type": "integer", "primaryKey": false, "notNull": false, @@ -1156,12 +1163,12 @@ }, "indexes": {}, "foreignKeys": { - "TeamInTournament_id_Tournament_id_fk": { - "name": "TeamInTournament_id_Tournament_id_fk", + "TeamInTournament_tournament_id_Tournament_id_fk": { + "name": "TeamInTournament_tournament_id_Tournament_id_fk", "tableFrom": "TeamInTournament", "tableTo": "Tournament", "columnsFrom": [ - "id" + "tournament_id" ], "columnsTo": [ "id" @@ -1169,12 +1176,12 @@ "onDelete": "no action", "onUpdate": "no action" }, - "TeamInTournament_id_Team_id_fk": { - "name": "TeamInTournament_id_Team_id_fk", + "TeamInTournament_team_id_Team_id_fk": { + "name": "TeamInTournament_team_id_Team_id_fk", "tableFrom": "TeamInTournament", "tableTo": "Team", "columnsFrom": [ - "id" + "team_id" ], "columnsTo": [ "id" @@ -1184,12 +1191,12 @@ } }, "compositePrimaryKeys": { - "TeamInTournament_id_id_pk": { + "TeamInTournament_tournament_id_team_id_pk": { "columns": [ - "id", - "id" + "team_id", + "tournament_id" ], - "name": "TeamInTournament_id_id_pk" + "name": "TeamInTournament_tournament_id_team_id_pk" } }, "uniqueConstraints": {} diff --git a/src/lib/drizzle/meta/_journal.json b/src/lib/drizzle/meta/_journal.json index 274e8d6..cd1278a 100644 --- a/src/lib/drizzle/meta/_journal.json +++ b/src/lib/drizzle/meta/_journal.json @@ -5,8 +5,8 @@ { "idx": 0, "version": "6", - "when": 1717341832866, - "tag": "0000_colorful_lady_vermin", + "when": 1717345116396, + "tag": "0000_thin_vindicator", "breakpoints": true } ] diff --git a/src/lib/drizzle/schema.ts b/src/lib/drizzle/schema.ts index e5b8c44..39a7019 100644 --- a/src/lib/drizzle/schema.ts +++ b/src/lib/drizzle/schema.ts @@ -120,7 +120,7 @@ export const MapInPool = sqliteTable("MapInPool", { // Foreign Keys mappool_id: integer("mappool_id").notNull().references(() => Mappool.id, { onDelete: "cascade", onUpdate: "cascade" }), map_id: integer("map_id").references(() => Map.id, { onDelete: "set null", onUpdate: "cascade" }), - settings_id: integer("tournamentSettingsId").references(() => Settings.id, { onDelete: "set null", onUpdate: "cascade" }), + settings_id: integer("settings_id").references(() => Settings.id, { onDelete: "set null", onUpdate: "cascade" }), }, (table) => ({ composite_key: primaryKey({ columns: [table.identifier, table.mappool_id] }) @@ -233,8 +233,8 @@ export const Team = sqliteTable("Team", { * A linker table for many-to-many relations between Team and Tournament */ export const TeamInTournament = sqliteTable("TeamInTournament", { - tournament_id: integer("id").references(() => Tournament.id), - team_id: integer("id").references(() => Team.id), + tournament_id: integer("tournament_id").references(() => Tournament.id), + team_id: integer("team_id").references(() => Team.id), }, (table) => ({ composite_key: primaryKey({ columns: [table.tournament_id, table.team_id] }) })) From 84e5aa2cbb31defd143fab530200b2f6bb9b544d Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sun, 2 Jun 2024 12:27:41 -0400 Subject: [PATCH 10/11] add dbml generation --- bun.lockb | Bin 133518 -> 134943 bytes package.json | 8 +- src/lib/drizzle/dbml.ts | 7 + src/lib/drizzle/schema.dbml | 256 ++++++++++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 src/lib/drizzle/dbml.ts create mode 100644 src/lib/drizzle/schema.dbml diff --git a/bun.lockb b/bun.lockb index 51342a0b16fa2604b353708a2d0028595f404506..6cf455139fa8f47326902ef73da95b36a2c07152 100755 GIT binary patch delta 21365 zcmeHv33yaRw*Rdro#cXH353uIAp{6(63E(tkX*J1Ap(ZQ5FkJ&X-FVs2NDpv*#s11 zDWC|*63`Jv91u_u9oc5w5EVxyC}P|h*<}#~e7{roUXtR>NrP+>rM~*W)KW}Ot^!(_dC@T1IR$bl&>_hUvq_?azKQBvBdMGQPfEXJ* z6{Ruoa$pjiXW)q?j-uS+d}W-`QK@svG-rvTJjK&kuxlUsXb9q=MX04pT@^Sw)dEJg-!V zMrR~9C2xu|JSQtk=?Df1l$JTlrj|NOC!qluG!~dTE_D{m!rZ8%S{ zbWkrrkaT>{D=Zyc!;HG(Qfj9tmz(OEhBwnS_XmcE`xjtpbq$z24HroHGe&)q!B2!R znOuxAKy@amX}4 z3wO~(IS{2u5P!B_D_2x2J=My~bYF&oCO!VZGyv7WMH9pG3d-UY&mi3%&_#uX`O4*% ziUMD_4?`=Z>RYW91zo#y3ZZbCqU;5q^dKQik!Z??ZS)*@O~)?xHWd6IupGDra0M{U zg^9qvz{7y4g8{(ghy-9V@OFsq@iV|w-=@7j;Q7EbcV-xLcn7_{B{1=G!6&^wzcrh@%?Oqh2D2TS(v#X*60$%`49$F10 zG~F<%%F6PbCH=bTu6JVg7nEUi(Yiqm415Hb`pI`rqyCjwKo6=9hA;%GfT^P#r?ZIW zGfD{epUC=a! zlDsJ;4)|SmiNVd~2R(yBruWpPCp#;Ui;D7fqE2HqD=Ty6DAPFe@=x*8bREu8xDu9S zLw8f?Tn0XkI~_EQZ$>Yj?hBeyE~hZNtR%0%nd8iwN->V-4ljRoZ*Sd8i})O`4z7`X zb=f3fnim}nyC*nG%Zkya#5uJzZ$gD~xS!tVs${*dFMw%2%?GA&)<-)`MfZhBJqgU1 z1oT%FOhNZI;FBLd0w(!B1EfBeI}Qah{-S}u0;c&hJ4GMNt7t$$-v~?{JPM;IOh*Um zikzicQ}gn3l#YY+dE*C6&SAjhgbNSo{7-?2eiNALUzB{zuPsK!5@1T#a)WjNQyQll z{CHq$*v_c;1@;AfCskMcJutQZ2$mk(VKaX_!Z@&Nt=8fkp@J%b2}{qw{pRFQ-<7HW)muP0Xyb z2|ZTsp4Q+|wQ+v81^aJqk1JT#zUtw{8`EBS!EY_Icrd=Mc@kUCtD9>UPYVz5Ph$Of zhQG$9^GbYv#jE`_wNpJs!9wJ=@*01;>IC%=sCqo4m0jHrDhZUgq;7y32+G1k{OznS zx7jqdm}l5D^`M8Mz)z4P9k)PXS#*0*E7qIa0yK4rRZ;rLwvb>acx8ZQY39jK1|+fj zxh+s*J9tK*re5>Z#h7dw&#MD9+deNvnU1DS;HSFR3?A9C1M9{!T59TkZ$*ibUDgEH z)eE4=01N`1b>g-lO&twahe-n*HoLkI6dCNnL9sV@b&zIhP@f01O2W7@T4`)Huf*qJ zUfoKwcr@Sv!AUHcX9R0(Gp`KR)YAy49qk+Qs$e^7&TXwVHi>7n*3@}ezPh1?k!E!_ zC~_bp$FNJ>7NW64o`KI9yfQ>ncOfIGUg05RH>h|}7U{+gSYi9=ZG-G=GOui-vFCU- zK2LF5Ta5+rjJ6mT77JHwQfOEBb1U#V7Jz#}~huYsZGc_nyJSX*`DDNMPb zD6?gl)E7V*#s%5c%b+N=P&W(-*+pXo+!m&(TQJXcsSu>lm%K7eLo!z5vx3{gHMWaq zglnp2fG%aBbg?64Y{(?v8=I!ZRW?c9U1)Gmcl|6P90p93C=wuY=Nc!cQv0daI`zrAV?t=?SwK zlo4hm3{omeQ*Rr*dK}Y@Mf1uijm_iLsQIe3qGZZms*nKrJR@3Dt3vdc!2bbui)R~t zGCIk6rVaLY{8V&;HLk5$nuk)V1o;0r&LopePSQ4r@jSySf6D zo)F}aPeI{+57*Hw?!YtRHCD_k@%a?5j@Q)V9rd=D#cl0sn@)NVzvR_DG_@6~X-?`P91N--D192N z1Qnszp`Qbws8=k=L3WEZoCowwQscvQXCaf@*)7w;X_B!$yt=2xe&n`9%^C>>>3lCrCeF|z0C=W&60r9C{JNc!g z4lIw`G))bTzMBk~jH7uacz*?tVuVTC#jdtQcGD;o?!bES0MF>9Sr>uVlhy`ygje^{ z)P}KoQYyR(>t;Vt_oD^Y++KF;qo8`wBx4`)>fV^@$X@aV;(-;i0F>c1WXubodZ7-H zg`UfxN~9k0c?q}m)zoeFyHg6SzW_z8<#^S07&@9z>rlIz14>_dLLj*r6lJEgkbTZ8 z`)R5#l9Lu9X(vWzOV-#@o{_AnZ=!~zJ!KwyLWuNAA6tilO5#DS64d2X(xu@0W1z_Q zdL%sYRfF0fN`38We^7ewpsWi(4dAEz6Vy*oA{%w7rYO=<0t&w94~qQm#j9ZdN>CIN zeMvlN)Je})NsOx4tH!Gj;*gqk=k0Ei`p z(~D!WS?8hHg9im9SYJcwLFq!D-e$s*iOJkHNK>bSM`n9T3qA)G1xjC18uz(N!R38G zk>UEvxEd7x$bG2$1Vsu5D1W=9QD1&?aFUweS2r2^46F>BL6HcWV>l;3JqSwXx!MtF zHAb)NYiIMh?Lp1@F?i8@Lz@Iu#TPAdlAOA#1`2=B zARlID@w{?`X6=D*a>;zdhy<$(rT((?7nD+DsS!-lYlowx^ERNQ%YA*fw$l)^wgja? zvhC}4dEN-a5XnnNNw0kpC0)x8DCwGG(#+l}P||saP|{m8!f^B!522JQ^;Myy%l!={ zUCuttBy0Rbq&PD(!8!}2{<3rgr4(86NjGbUqNMZIqom7ydAGL1NVB#Gr9rao zYj=5`8RRtTV+2Zi?G}`DEoV^DHAjsydz+4u&O3mT-oj_J*2fk24%A6$Q5*cLSO2 z!$C!XLM|hUkANZ#h!WO;S3r>lOuT5jdIuE66L)oN==wVJI?OuM%>qU3pamn@4~itQ zP+@jiv-EqB{>5!5DAFmvbg4@~QC3*xw~)6%(YhnoU~7YHNJ@*7Q6ed5W1Hgs{Sf+AZ~+{A6B|`k)i3V79bua`I7=lGNj1_61XRYKfh| zPfkjr?c-!kwM^7^L0GY{Xms(gN)MNxBA>b_p1^?sFF+drU3GCi(4hbZXb+(4zk;cKCjepW zw4@$vt|rMs1Q>MH#UvOhxxbB7$RLXHs*A}`xLsa^EqqpmKYy}-9?{APAbakGGD-FZ z&{Y>(K=%a%1CS2#s*9-}v6bx+IeGmS_JBklrMM3Y({y=>$$;qweJ^a~8w!K@bA^p1 zJTXHb!YrdjT}+y01IT%EjC#V<^#X&gi%I?wgHM=-w8+4Z8vJ`;=|ZJ$1*Odjqrq=s z>To6CKEOr*8MXyL{H*}G?uE&)r(`W*Y<`LHG{6Qp03ZY20MJF46uwCWF2YvsQ|vG8 zJ|=mJ@>`f%zh}r1CVw6`@J9xpFqvNss1NuGK-X_z-EY4k@b45*2j2n6fWHCAupa<4 z{Br=h?uDuT0)XT%0*JnhwH!;3Gf%~fpV#VXb!oy4bdCyXBKx>{~+L%@rh2DWG zd`hW5C7O~5iWo^G58O-E&YJC?LWREcVPGou!v_VfKQPe)@ImGdCc?l}9AeOfE&TTE zV5}0@>KWX+m{`LMK4H@SkUN^9}wzuuBf3&=4##1nXjoM1{d8Op0e3G+`<}Y|wQv z$;}3z+%yN6=y|~Y!0Qb8bF0=42!mfX3(Y*{IqhH1cjevefK^I|~P=5uck$-IP3DXUMes@8v&kcOq zz+Vs(7hz9Y6~8qYb+Hu!KY&k)&l&ZEsd(PN7Yuxnn79a2@sfcr8~nPM^j!g;b^#28 zH|3v7++SfbfPRBQIvN2}7W)Fzv}_KHKcxkI{0EriTB4rX1sig8F|k7MVdfvbeUm^g z{U`1PU2=rs=#)lUcMk|s(lmnq(Y+w_B?73wB!xd(QUCXi;ool%$uo}t=pszH^83b6 z&zRpghX3OmMRN%v#gux#Zw#dye%}}(7k=Lu{=PB1*M<{6}mIcaND@ zmDj6YE9c4?2Tu+QdwzZ7$1z*F6}`~8Z18|*tJdl*6O6M&u`|zokQt^A1gP`676?!=pZ@h{xr}Oe3 zefUS9`ty(<(|N}$K77HCsVs$m0O|y&*ej_lmCw17&KF(v;opE7#3Qe!^Z08%eD&2- z{IH`2)c2s0ucfjyzT#RsUwhq$Uj;Rc_r9La2mIv2pSqsPM(|6ZegZY(r&N~CtA4`x zZeV;jQdtI1yMgiD#P~ps=IkcM_cO+KGnHlXT{qL&Sg!s&EQsbt_uYM7$Q(f>efw52 zwPY%lukxy&o3j58KK-u3nnns9O9PufQG1@xx!siguld});TP`3Ziz@Q*7U!N5^v#w zI396GKbSxM&F!ZDsF5P}YaaQ_{88{25#o)m|KZ4Q48DNjE2}heQfYXFV@ke~BOEF^ z|5u@x-m1?&VXh;+^`9#q18xip$z}gUp3D6&>e%QPKgsM1B>=ARnW8jUZTMx{l=pdmwcf@_4L#>89+{1el)2 zn%}eNWe)!6C+5o60J;W(L2a;KQC0!S&<6}T+;rrkKt>HRc;u-(02xK^d+?a>6+mA=KL7>$ zegN(82LMt;lT0=`#ergP0F9bP-vU5y-~s^j47(YCVo1-og8&vlJpko3J?*asP&n6% zy-??>L~$yh9FPx~03au30kQ!(0Q!*tek!7jL7DtI7LX1Y2^bEbw|hwdN=wRX%6FOv zF@RWr9nclf4G;|og)VxY^%cd8(&$?Ny(~T{HjHI~t}jtM05}LZ1UL*h0{AmvE8s~0 zy((V=SPNJW*Z?R8%mhpW&?DK!0QwC;F(3=j3xK^E{rF8jJnssO&7^#y-x8R<9JE42 zv382N`VZfsRn(!rnC;)z=K)-FG|9OyaYiK^7 zLz(6<$@|a;fd=?qyf&Vt`@RU73n0f+P7-^voY#ICAnA24y$UA#;sCKPWjNRyo*tBb zq9&WAii_FI$3;UholY6~Db!Fl5s&5~VUthU{33W}CND*qGCL8F3Luw|5BGsj!KBQm zAy5#>WyB*_QP632An-03d2&7}rbW~2@CIlyj)FrAqG<#z2GqfG0Mif}9~pfUKrx`j zvhKi0j_N71NEZ!~rs7umJ?JtJP7)*-j4>5Jk5Q= z1TFGG;99a(%*bPZ@o$cVH2-X#e#Y}T(e}&lx5ML7PN_o zLX*4y-(5M$ak40;+}FZrq&|=}|3^EpU&+nvHV1+%j1sjiYE}T_Zsgu`rqu%%%Y{ci zD~mk_UL)}Sn793-qfP(R96dxubc;aVoIiyiqG#!XR^ zk3qd8eg+CW1V>?Jkdn3f7p$O|vwdgv9*<#IqjUUCH`1Jnkn~ES13jxxH zp6)}_+xcu~QJa1zQ4@nv-fbFa{&)O{56`xnQP?;G0(M<@oY)23?7Vn~knE|s2O7G> zFVv^`@ADsweD?j6E1SNtu-OE(R4~Jmx>x2ezrV zDQ$BMn!@!`V3wEz0k%}EC$v_$*0bi~odRZOPlfx5?gF4WYK}- zJ^%8zv~~MoNNhw@94uKXiZ?>da^Y3PlG#u(sECEIDp6Pj^UZ%14}1Hgvpe2znrvZ+ zzI2)S&*Z22_WtZt+RbMy3^Ai|DM!U?MF`Fbaj6K|_`T4Iq5YD0eLAy=l42HsXB10| zS+vF5M|@t+T3DL;h|h{y6l*7%R6wL-2@41`|JS|2w27{dPT%Q5+9M-q9ZM9MCD7hq ztSEunVWM|A+8jX}HddS_)+F)4R2D75O2H}@{YxR-QOqnwO|)1|)ZbfltCY?C73+mE z7GqksW-5y@EHnBPxl>uL(F?w7S*Nk+So2^0eVYF?>f(|wW*MP^H_U(P*T!C+cC+uM z=W2u4Urd>XD4VAQBvT(I?L{NWfij_$Vo^N(*IuaWdvRYmhAbT$&15WX;_-4e*z`!C zd0fC-e@uEMXL!%nq#CmYgOw3nZwj(P@kRxlV;(DT!>7$&zh0X!TG)A;KHbd28M-nq z#=hgYf}F(C5)mDvToherz&Tlg`YQB(Y_s7RpIz~4rq5X1+lmCjW@G!rERs78xn>w` za`J#B4>$A3ZN`!kDPba&yCbJ`9& zDx1cWOs<#%0X9{vC%FZXqxJ5!qkHf7uDpMAt)f-py_ty27E$kEc82W`=N?9@%ff3G zCW~i~=sAl$5ZDA;Ct72leeu?iKPGj#?LmuzToYS~t+UvmK=W{gBa8leY}A$aZPKT5 z)$kV$W}|=eG=^^mpMU1~#u`PgNQfY|3__cY8T*!43OU>=o}SGr5_^T{|KD^9n14ZB6eMZkM!P(#jd9yfJr*n;!4tWpg!__oM&VL%CDg$oJ?i0woT6Q@DN znrAVj`G!|CdVg|~2eK$SA`%WWPivUoc1z>aOCHXztywO@-57y+yu%cxe!Os1_U2lF z*MtKC>_agVsHJ)8!tQgGEuPqRm1Yi20>sk?-&5SI1(OEa0?l(CmS1~n^D9C1=0Y$U z#$ar@;x_eY9{iyF;mob5Rs~n3fLz7ri^w_XafV0*3N#OdC>gl#eAtQb?T|B;>~P_l z1K;Xv?LG23DUohPQD$BnhMC7T*b?ho;=C&A%MrwrYyTjIApc{{^Bra{+kG^+VL%(B zLoAf$2@oS^UjL@4Ysag#rhF_m%tai&6(10~D6I2XbW8K3iM-UweqC2Cc1v-YSKeL3 z@OdmMuw@s0MOih@U(5Q;Ct2n<+!@;~R8-A_50;AkK!Mwl@pO;h6zUG^vcQ?unC6&V zx)+HH5Ex*dH8DOVyFr`9Bj{#J_i1ca&C@7uG;vP86Z3ARG$JML5wze?PY7Vaz@ix6lflZQE;RCPlF~64V2x<`S+vPwGbn}CEfuFG*9MeJ#FC5l4b)B z$boey@9MjtK=TNX5!E$ae1lVGNCA0k5aPW>xS2k%2shv=G@zC8rFW*Fl+=->Q*4$px#UNL!4a%)>tFZ>Tvr-|MSr*^^Ao`C=0Z^z5NOOnWHp zoxzUAd)|NmmLKY=zc{xT5$h=u9)*YA6(b(S=4iV35EKT)q|u zA7eI)pC&$g3>%VVqR|pG%NCuMur6xrUixVpGejo1EzJWyCMT|1RQ%y*)G78;)G3;; zT*4+`=Y3-d7UV^J^cB1Qne-rS^OBnoG`6KO4Qwn)%v_3YMvB!-Vb)>s6(OuEkAt~N zqyhzgfkzZ{&qxR!Fm}eufvM0z(LhE82-o9C5;>S=o^soKM7;YrTaP_p-ZHbs7HFK^ z;U2Q%gX!l!vBgR&q!YgqA1p&p7sU@if#wk&Kit>a)?jXERIRnyB6vC6FnXZ;8t>jK zhAoHsqhjH5mfW^os=heL12SOf=byj6VSChT-Dzo#>>d#rrOXvIoHgqq%jU5fLzCX` z(lV&Y)3s9O!5b}Z-i#djcAT@e=730C0sG98I=b~)H|{0RMwVKE??o{L*d6g0$(bj8 zAZL7@meYK1d;9c=Vg{?9iFJIaR{H4=)gR3 zq_c0wX!h7wRkZ?3L~jV-Ha?o<^fOCvpv{`H%T?O7{k3v$iaD!Uvjpi8^Q04=aJKEF zrRx^eN||S&9QPQIefTlq6IFql> zz7lYt_3aO&fV|bq@Y>iK@iWQYGmP>0=Aax9T~|Tio?(;%GK|eUW%-VnMZ))tr4*2{ zv|&Ylhve=VGb!f~zmUK^VQh(W6%e9yp1VHr3Z`&6ulT+4d~NXj8V@2~!k z0wg75fSLu%@^RcZ8(`{~hk;1nM$tC`(ehyyAU4uR+`}wJyi6bSL1HgOThAer(Nu2s z&rW=Ik?#*}YPXbIu-PP~5sl6*{P^pyg}iBFXA{xwKi#exJ7>8mwFORvqQ+1(ZFrb9 z^w@&OYrD{Q&O`n?JLerx+5$?g69-N{-JnYiS%$Av#~}tMHk;aU$G+n%i`!*UR)-eI$pG2i?x2fSh^NDW1htH zdf57t2_sqzL~q7jbG10Q7R%)oaTO@GheHq8i1BBCxw+hN4RW}*l2yAiSkPHY{?eSRn~e!4#U>cJb9^R(Whm*2EXl%<}sMTXl{7U z5}qR>FvdXhU>vW(Gp84II^V~_;;61F&znd*&Y-Z~Lh+GXo$uWX;65^~@S*oVw$F^GwWhQ+IxT)*MxoA|GDZEccA7 z_;x)DyBknF)|P=eBJK%{--wl%`$V0f>)UJb;uEmcZ-O`uL1W8pSvx_r-oRSKR!z_o zV)Dr!Pds*e;xY^CEHg_{%oBgErS#a==iP)QwKdnplnqET<3Y(~Q3ZVv9$v zxJVtC2LL^@+xO*z@3omwM-95B$++%<`|!q+{kv;xjIRaeSwYW?N?Y9Io9)HF7BDQR ze_|_>HlKJ>Jin2Zuu&pp6V6uL(n;69`o*A~%@^(r-C@ub`(EsrcJ$(jmqF7mVsM}I zVh-wEO}|wX4Yto*tDN{clrC8uHjvC oO7dpR$fqM6>oy6;22_OXWFge5r6sDnsCtcsytMTe`{BNS12vJXE&u=k delta 20757 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 Mappool.id + +ref: MapInPool.tournamentSettingsId > Settings.id + +ref: MapInPool.map_id > Map.id + +ref: MapStats.map_id > Map.id + +ref: MappoolInRound.round_id > Round.id + +ref: MappoolInRound.mappool_id > Mappool.id + +ref: MatchBlock.acted_on_by_id > TeamInMatch.id + +ref: MatchBlock.(map_identifier, pool_id) > MapInPool.(identifier, mappool_id) + +ref: MatchBlock.section_id > BlockSection.id + +ref: Match.settings_id > Settings.id + +ref: Match.round_id > Round.id + +ref: Match.current_section_id - BlockSection.id + +ref: Match.block_in_section_id - MatchBlock.id + +ref: ModMultiplier.settings_id - Settings.id + +ref: Round.tournament_id > Tournament.id + +ref: Score.team_score_id > TeamScore.id + +ref: Score.user_id > User.id + +ref: Score.block_id > MatchBlock.id + +ref: TeamInMatch.team_id > Team.id + +ref: TeamInMatch.match_id - Match.id + +ref: TeamInTournament.tournament_id > Tournament.id + +ref: TeamInTournament.team_id > Team.id + +ref: TeamScore.team_id > Team.id + +ref: TeamScore.block_id > MatchBlock.id + +ref: Tournament.settings_id > Settings.id + +ref: UserInTeam.team_id > Team.id + +ref: UserInTeam.user_id > User.id \ No newline at end of file From 0efba61592415a07b1e64db986372fdbadd798bb Mon Sep 17 00:00:00 2001 From: clxxiii Date: Sun, 2 Jun 2024 18:51:53 -0400 Subject: [PATCH 11/11] move some stuff around --- bun.lockb | Bin 134943 -> 134943 bytes drizzle.config.ts | 2 +- src/graphql.ts | 42 ---------------------- src/graphql/index.ts | 10 ++++++ src/lib/drizzle/dbml.ts | 4 +-- src/lib/drizzle/index.ts | 10 +++--- src/lib/drizzle/{ => schema}/relations.ts | 20 +++++++++-- src/lib/drizzle/{ => schema}/schema.ts | 0 8 files changed, 36 insertions(+), 52 deletions(-) delete mode 100644 src/graphql.ts create mode 100644 src/graphql/index.ts rename src/lib/drizzle/{ => schema}/relations.ts (91%) rename src/lib/drizzle/{ => schema}/schema.ts (100%) diff --git a/bun.lockb b/bun.lockb index 6cf455139fa8f47326902ef73da95b36a2c07152..fcf582a8443b6efcbb41e425ee87871d9b006986 100755 GIT binary patch delta 67 zcmV-J0KEU7o(P|w2(W+_39S delta 64 zcmbO~k7NEkjtvcBlLO=wCMQTpY~CRz@r>7Uv(u*7PzEqy+Whg)X~xMP{)lYe^N%x+ Ooe3hm{Y(yH@FD;M&=&>( diff --git a/drizzle.config.ts b/drizzle.config.ts index 0ee60de..6aca453 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -4,7 +4,7 @@ import { defineConfig } from 'drizzle-kit'; export default defineConfig({ dialect: 'sqlite', out: './src/lib/drizzle', - schema: ["./src/lib/drizzle/schema.ts", "./src/lib/drizzle/relations.ts"], + schema: "./src/lib/drizzle/schema/*.ts", dbCredentials: { url: 'file:../yagami-db/dev.db' }, diff --git a/src/graphql.ts b/src/graphql.ts deleted file mode 100644 index d15c05e..0000000 --- a/src/graphql.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { db } from "./lib/drizzle" -import { buildSchema } from "drizzle-graphql" -import { GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, graphql } from "graphql" - -const { entities } = buildSchema(db); - - -const schema = new GraphQLSchema({ - query: new GraphQLObjectType({ - name: 'Query', - fields: { - getMap: entities.queries.mapinpool, - getMappool: entities.queries.mappool, - getMatch: entities.queries.match, - getTeam: entities.queries.team, - getTournament: entities.queries.tournament, - getUser: entities.queries.user, - getSettings: entities.queries.settings - } - }), - mutation: new GraphQLObjectType({ - name: 'Mutations', - fields: { - updateSettings: { - type: new GraphQLList(new GraphQLNonNull(entities.types.SettingsItem)), - args: { - set: { - type: new GraphQLNonNull(entities.inputs.SettingsUpdateInput), - }, - where: { - type: entities.inputs.SettingsFilters - } - }, - resolve: entities.mutations.updateSettings.resolve - }, - duplicate: entities.mutations.updateSettings - } - }) -}) -export const sendQuery = (query: string) => { - return graphql({ schema, source: query }) -} \ No newline at end of file diff --git a/src/graphql/index.ts b/src/graphql/index.ts new file mode 100644 index 0000000..2ae9f4e --- /dev/null +++ b/src/graphql/index.ts @@ -0,0 +1,10 @@ +import { db } from "../lib/drizzle" +import { buildSchema } from "drizzle-graphql" +import { GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, graphql, printSchema } from "graphql" + +export const { entities, schema } = buildSchema(db, { "relationsDepthLimit": 1 }); + + +export const sendQuery = (query: string) => { + return graphql({ schema, source: query }) +} \ No newline at end of file diff --git a/src/lib/drizzle/dbml.ts b/src/lib/drizzle/dbml.ts index 6821984..193da95 100644 --- a/src/lib/drizzle/dbml.ts +++ b/src/lib/drizzle/dbml.ts @@ -1,7 +1,7 @@ -import { data } from "." +import { schema } from "." import { sqliteGenerate } from "drizzle-dbml-generator"; const out = "./src/lib/drizzle/schema.dbml" const relational = true; -sqliteGenerate({ schema: data, out, relational }) \ No newline at end of file +sqliteGenerate({ schema, out, relational }) \ No newline at end of file diff --git a/src/lib/drizzle/index.ts b/src/lib/drizzle/index.ts index 2469a3b..beb87f9 100644 --- a/src/lib/drizzle/index.ts +++ b/src/lib/drizzle/index.ts @@ -1,11 +1,11 @@ import { drizzle } from "drizzle-orm/libsql" import { createClient } from "@libsql/client"; -import * as schema from "./schema" -import * as relations from "./relations" +import * as tables from "./schema/schema" +import * as relations from "./schema/relations" const client = createClient({ url: "file:../yagami-db/dev.db" }) -const data = { ...schema, ...relations } -const db = drizzle(client, { schema: data }); +const schema = { ...tables, ...relations } +const db = drizzle(client, { schema }); -export { data, db } \ No newline at end of file +export { schema, db } \ No newline at end of file diff --git a/src/lib/drizzle/relations.ts b/src/lib/drizzle/schema/relations.ts similarity index 91% rename from src/lib/drizzle/relations.ts rename to src/lib/drizzle/schema/relations.ts index 463df20..543db06 100644 --- a/src/lib/drizzle/relations.ts +++ b/src/lib/drizzle/schema/relations.ts @@ -142,7 +142,17 @@ export const MatchRelations = relations(Match, ({ one, many }) => ({ export const BlockSectionRelations = relations(BlockSection, ({ one, many }) => ({ for_match: one(Match, { fields: [BlockSection.match_id], - references: [Match.id] + references: [Match.id], + relationName: 'section_list' + }), + current_for: one(Match, { + fields: [BlockSection.match_id], + references: [Match.current_section_id], + relationName: 'current_section' + }), + mappool: one(Mappool, { + fields: [BlockSection.mappool_id], + references: [Mappool.id] }), blocks: many(MatchBlock), })); @@ -160,6 +170,11 @@ export const MatchBlockRelations = relations(MatchBlock, ({ one, many }) => ({ fields: [MatchBlock.section_id], references: [BlockSection.id] }), + current_for: one(Match, { + fields: [BlockSection.match_id], + references: [Match.block_in_section_id], + relationName: 'current_block' + }), Scores: many(Score), TeamScores: many(TeamScore), })); @@ -172,7 +187,8 @@ export const TeamInMatchRelations = relations(TeamInMatch, ({ one, many }) => ({ }), match: one(Match, { fields: [TeamInMatch.match_id], - references: [Match.id] + references: [Match.id], + relationName: 'team_list' }), })); diff --git a/src/lib/drizzle/schema.ts b/src/lib/drizzle/schema/schema.ts similarity index 100% rename from src/lib/drizzle/schema.ts rename to src/lib/drizzle/schema/schema.ts