4 Commits
Author SHA1 Message Date
legonzaur cbd853fb56 add model 2023-06-22 18:15:56 +02:00
legonzaur 1fcf9627a6 fix small mistakes on migration 2023-06-22 18:15:52 +02:00
legonzaur 04a9c935e7 table creation for v3 2023-06-22 18:01:04 +02:00
legonzaur aa96ada505 eslint format 2023-06-22 17:39:19 +02:00
3 changed files with 298 additions and 71 deletions
+25 -25
View File
@@ -1,52 +1,52 @@
import { promises as fs } from "fs"; import { promises as fs } from 'fs'
import { import {
FileMigrationProvider, FileMigrationProvider,
Kysely, Kysely,
Migrator, Migrator,
PostgresDialect, PostgresDialect
} from "kysely"; } from 'kysely'
import * as path from "path"; import * as path from 'path'
import { Pool } from "pg"; import { Pool } from 'pg'
import Database from "./model"; import type Database from './model'
async function migrateToLatest() { async function migrateToLatest () {
const db = new Kysely<Database>({ const db = new Kysely<Database>({
dialect: new PostgresDialect({ dialect: new PostgresDialect({
pool: new Pool({ pool: new Pool({
host: process.env.POSTGRES_HOST, host: process.env.POSTGRES_HOST,
database: process.env.POSTGRES_DATABASE, database: process.env.POSTGRES_DATABASE,
user: process.env.POSTGRES_USER, user: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD, password: process.env.POSTGRES_PASSWORD
}), })
}), })
}); })
const migrator = new Migrator({ const migrator = new Migrator({
db, db,
provider: new FileMigrationProvider({ provider: new FileMigrationProvider({
fs, fs,
path, path,
migrationFolder: path.join(__dirname, "./migrations"), migrationFolder: path.join(__dirname, './migrations')
}), })
}); })
const { error, results } = await migrator.migrateToLatest(); const { error, results } = await migrator.migrateToLatest()
results?.forEach((it) => { results?.forEach((it) => {
if (it.status === "Success") { if (it.status === 'Success') {
console.log(`migration "${it.migrationName}" was executed successfully`); console.log(`migration "${it.migrationName}" was executed successfully`)
} else if (it.status === "Error") { } else if (it.status === 'Error') {
console.error(`failed to execute migration "${it.migrationName}"`); console.error(`failed to execute migration "${it.migrationName}"`)
} }
}); })
if (error) { if (error) {
console.error("failed to migrate"); console.error('failed to migrate')
console.error(error); console.error(error)
process.exit(1); process.exit(1)
} }
await db.destroy(); await db.destroy()
} }
export default migrateToLatest; export default migrateToLatest
@@ -0,0 +1,140 @@
import { sql, type Kysely } from 'kysely'
export async function up (db: Kysely<any>): Promise<void> {
await db.schema.createSchema('ToneAPI').ifNotExists().execute()
await db.schema.createTable('ToneAPI.host')
.addColumn('host_name', 'varchar(50)', (col) => col.notNull())
.addColumn('host_id', 'integer', (col) => col.notNull().primaryKey().autoIncrement())
.addColumn('host_token', 'varchar(50)', (col) => col.notNull().defaultTo(sql`gen_random_uuid()`))
.execute()
await db.schema.createTable('ToneAPI.server')
.addColumn('server_name', 'varchar(64)', (col) => col.notNull())
.addColumn('host_id', 'integer', (col) => col.notNull().references('ToneAPI.host.host_id'))
.addPrimaryKeyConstraint('server_pkey', ['server_name', 'host_id'])
.execute()
await db.schema.createTable('ToneAPI.match')
.addColumn('match_id', 'integer', (col) => col.notNull().primaryKey().autoIncrement())
.addColumn('host_id', 'integer', (col) => col.notNull().primaryKey())
.addColumn('server_name', 'varchar(64)', (col) => col.notNull())
.addColumn('game_map', 'varchar(30)', (col) => col.notNull())
.addColumn('gamemode', 'varchar(10)', (col) => col.notNull())
.addColumn('air_accel', 'boolean', (col) => col.notNull().defaultTo(false))
.addForeignKeyConstraint('fk_match_host_of_server', ['host_id', 'server_name'], 'ToneAPI.server', ['host_id', 'server_name'])
.execute()
await db.schema.createTable('ToneAPI.player')
.addColumn('player_id', 'bigint', (col) => col.notNull().primaryKey())
.addColumn('player_name', 'varchar(50)', (col) => col.notNull())
.execute()
await db.schema.createTable('ToneAPI.weapon')
.addColumn('weapon_id', 'varchar(50)', (col) => col.notNull().primaryKey())
.addColumn('weapon_name', 'varchar(50)', (col) => col.notNull())
.execute()
await db.schema.createTable('ToneAPI.mods_on_weapon')
.addColumn('mod_id', 'integer', (col) => col.notNull().primaryKey())
.addColumn('speedloader', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('extra_ammo', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('gunrunner', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('gun_ready', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('quickswap', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('tactikill', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('suppressor', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('ricochet', 'boolean', (col) => col.notNull().defaultTo(false))
.addColumn('pro_screen', 'boolean', (col) => col.notNull().defaultTo(false))
.execute()
await db.schema.createTable('ToneAPI.titan_chassis')
.addColumn('titan_id', 'varchar(30)', (col) => col.notNull().primaryKey())
.addColumn('chassis_name', 'varchar(30)', (col) => col.notNull())
.execute()
await db.schema.createTable('ToneAPI.loadout')
.addColumn('loadout_id', 'integer', (col) => col.notNull().primaryKey().autoIncrement())
.addColumn('primary_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('primary_mod_id', 'integer', (col) => col.references('ToneAPI.mods_on_weapon.mod_id'))
.addColumn('secondary_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('secondary_mod_id', 'integer', (col) => col.references('ToneAPI.mods_on_weapon.mod_id'))
.addColumn('anti_titan_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('anti_titan_mod_id', 'integer', (col) => col.references('ToneAPI.mods_on_weapon.mod_id'))
.addColumn('ordnance', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('tactical', 'varchar(50)')
.addColumn('titan_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('pilot_passive_1', 'varchar(50)')
.addColumn('pilot_passive_2', 'varchar(50)')
.addColumn('titan_passive_1', 'varchar(50)')
.addColumn('titan_passive_2', 'varchar(50)')
.addColumn('titan_passive_3', 'varchar(50)')
.addColumn('titan_passive_4', 'varchar(50)')
.addColumn('titan_passive_5', 'varchar(50)')
.addColumn('titan_passive_6', 'varchar(50)')
.addColumn('titan_special', 'varchar(50)')
.addColumn('titan_anti_rodeo', 'varchar(50)')
.addColumn('titan_primary_mod', 'varchar(50)')
.addColumn('titan_id', 'varchar(50)', (col) => col.references('ToneAPI.titan_chassis.titan_id'))
.execute()
await db.schema.createTable('ToneAPI.kill')
.addColumn('kill_id', 'bigint', (col) => col.notNull().primaryKey().autoIncrement())
.addColumn('attacker_id', 'bigint', (col) => col.notNull().references('ToneAPI.player.player_id'))
.addColumn('victim_id', 'bigint', (col) => col.notNull().references('ToneAPI.player.player_id'))
.addColumn('match_id', 'integer', (col) => col.notNull().references('ToneAPI.match.match_id'))
.addColumn('attacker_loadout_id', 'integer', (col) => col.notNull().references('ToneAPI.loadout.loadout_id'))
.addColumn('victim_loadout_id', 'integer', (col) => col.notNull().references('ToneAPI.loadout.loadout_id'))
.addColumn('attacker_speed', 'integer')
.addColumn('victim_speed', 'integer')
.addColumn('attacker_movementstate', 'varchar(50)')
.addColumn('victim_movementstate', 'varchar(50)')
.addColumn('distance', 'integer')
.addColumn('unix_time', 'timestamp')
.addColumn('game_time', 'decimal')
.addColumn('cause_of_death', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('attacker_held_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.addColumn('victim_held_weapon', 'varchar(50)', (col) => col.references('ToneAPI.weapon.weapon_id'))
.execute()
await db.schema.createTable('ToneAPI.titan_stats_in_match')
.addColumn('match_id', 'integer', (col) => col.notNull().references('ToneAPI.match.match_id'))
.addColumn('player_id', 'bigint', (col) => col.notNull().references('ToneAPI.player.player_id'))
.addColumn('titan_id', 'varchar(50)', (col) => col.notNull().references('ToneAPI.titan_chassis.titan_id'))
.addColumn('playtime', 'bigint')
.addColumn('shots_fired', 'integer')
.addColumn('shots_hit', 'integer')
.addColumn('headshots', 'integer')
.addPrimaryKeyConstraint('titan_stats_in_match_pkey', ['match_id', 'player_id', 'titan_id'])
.execute()
await db.schema.createTable('ToneAPI.weapon_stats_in_match')
.addColumn('match_id', 'integer', (col) => col.notNull().references('ToneAPI.match.match_id'))
.addColumn('player_id', 'bigint', (col) => col.notNull().references('ToneAPI.player.player_id'))
.addColumn('weapon_id', 'varchar(50)', (col) => col.notNull().references('ToneAPI.weapon.weapon_id'))
.addColumn('playtime', 'bigint')
.addColumn('shots_fired', 'integer')
.addColumn('shots_hit', 'integer')
.addColumn('headshots', 'integer')
.addColumn('ricochets', 'integer')
.addPrimaryKeyConstraint('weapon_stats_in_match_pkey', ['match_id', 'player_id', 'weapon_id'])
.execute()
await db.schema.createTable('ToneAPI.player_stats_in_match')
.addColumn('match_id', 'integer', (col) => col.notNull().references('ToneAPI.match.match_id'))
.addColumn('player_id', 'bigint', (col) => col.notNull().references('ToneAPI.player.player_id'))
.addColumn('shots_fired', 'integer')
.addColumn('shots_hit', 'integer')
.addColumn('headshots', 'integer')
.addColumn('ricochets', 'integer')
.addColumn('overall_distance_covered', 'bigint')
.addColumn('time_grounded', 'bigint')
.addColumn('time_wall', 'bigint')
.addColumn('time_air', 'bigint')
.addPrimaryKeyConstraint('playerstats_in_match_pkey', ['match_id', 'player_id'])
.execute()
}
export async function down (db: Kysely<any>): Promise<void> {
}
+133 -46
View File
@@ -1,47 +1,129 @@
import { type Generated } from 'kysely' import { type Generated } from 'kysely'
interface HostTable {
host_name: string
host_id: Generated<number>
host_token: Generated<string>
}
interface ServerTable {
server_name: string
host_id: number
}
interface MatchTable {
match_id: Generated<number>
host_id: number
server_name: string
game_map: string
gamemode: string
air_accel: boolean
}
interface PlayerTable {
weapon_id: string
weapon_name: string
}
interface WeaponTable {
playername: string
player_id: number
}
interface ModsOnWeaponTable {
mod_id: number
speedloader: boolean
extra_ammo: boolean
gunrunner: boolean
gun_ready: boolean
quickswap: boolean
tactikill: boolean
suppressor: boolean
ricochet: boolean
pro_screen: boolean
}
interface TitanChassisTable {
titan_id: string
chassis_name: string
}
interface LoadoutTable {
loadout_id: Generated<number>
primary_weapon: string
secondary_weapon: string
anti_titan_weapon: string
primary_mod_id: number
secondary_mod_id: number
anti_titan_mod_id: number
ordnance: string
tactical: string
titan_weapon: string
pilot_passive_1: string
pilot_passive_2: string
titan_passive_1: string
titan_passive_2: string
titan_passive_3: string
titan_passive_4: string
titan_passive_5: string
titan_passive_6: string
titan_special: string
titan_anti_rodeo: string
titan_primary_mod: string
titan_id: string
}
export interface KillTable { export interface KillTable {
id: Generated<number> kill_id: Generated<bigint>
servername: string attacker_id: bigint
host: number victim_id: bigint
killstat_version: string match_id: number
match_id: string attacker_loadout_id: number
game_mode: string victim_loadout_id: number
map: string attacker_speed: number
unix_time: Generated<Date> victim_speed: number
game_time: number attacker_movementstate: string
player_count: number victim_movementstate: string
attacker_name: string
attacker_id: string
attacker_current_weapon: string
attacker_current_weapon_mods: number
attacker_weapon_1: string
attacker_weapon_1_mods: number
attacker_weapon_2: string
attacker_weapon_2_mods: number
attacker_weapon_3: string
attacker_weapon_3_mods: number
attacker_offhand_weapon_1: string
attacker_offhand_weapon_1_mods: number
attacker_offhand_weapon_2: string
attacker_offhand_weapon_2_mods: number
victim_name: string
victim_id: string
victim_current_weapon: string
victim_current_weapon_mods: number
victim_weapon_1: string
victim_weapon_1_mods: number
victim_weapon_2: string
victim_weapon_2_mods: number
victim_weapon_3: string
victim_weapon_3_mods: string
victim_offhand_weapon_1: string
victim_offhand_weapon_1_mods: number
victim_offhand_weapon_2: string
victim_offhand_weapon_2_mods: number
cause_of_death: string
distance: number distance: number
titan?: string unix_time: Date
game_time: number
cause_of_death: string
attacker_held_weapon: string
victim_held_weapon: string
}
export interface TitanStatsInMatchTable {
match_id: number
player_id: bigint
titan_id: string
playtime: bigint
shots_fired: number
shots_hit: number
headshots: number
}
export interface WeaponStatsInMatchTable {
match_id: number
player_id: bigint
weapon_id: string
playtime: bigint
shots_fired: number
shots_hit: number
headshots: number
ricochets: number
}
export interface PlayerStatsInMatchTable {
match_id: number
player_id: bigint
shots_fired: number
shots_hit: number
headshots: number
ricochets: number
overall_distance_covered: bigint
time_grounded: bigint
time_wall: bigint
time_air: bigint
} }
export interface KillViewTable { export interface KillViewTable {
@@ -59,15 +141,20 @@ export interface KillViewTable {
total_distance: number total_distance: number
} }
interface HosterTable {
id: Generated<number>
name: string
token: Generated<string>
}
interface Database { interface Database {
kill_view: KillViewTable kill_view: KillViewTable
host: HostTable
server: ServerTable
match: MatchTable
player: PlayerTable
weapon: WeaponTable
mods_on_weapon: ModsOnWeaponTable
titan_chassis: TitanChassisTable
loadout: LoadoutTable
kill: KillTable kill: KillTable
host: HosterTable titan_stats_in_match: TitanStatsInMatchTable
weapon_stats_in_match: WeaponStatsInMatchTable
player_stats_in_match: PlayerStatsInMatchTable
} }
export default Database export default Database