From 125d3a3f662ce5d46f89b0a333c9bfd58720aef4 Mon Sep 17 00:00:00 2001
From: Dennis Postma <dennis@directonline.io>
Date: Wed, 25 Dec 2024 01:16:07 +0100
Subject: [PATCH] Added init migration, moved ORM config into separate file,
 updated .gitignore file

---
 .gitignore                            |  1 +
 migrations/Migration20241225000904.ts | 76 +++++++++++++++++++++++++++
 mikro-orm.config.ts                   | 26 +++++++++
 src/server.ts                         | 12 ++---
 src/utilities/database.ts             | 23 ++------
 5 files changed, 112 insertions(+), 26 deletions(-)
 create mode 100644 migrations/Migration20241225000904.ts
 create mode 100644 mikro-orm.config.ts

diff --git a/.gitignore b/.gitignore
index 39ee9ef..f406706 100644
--- a/.gitignore
+++ b/.gitignore
@@ -311,5 +311,6 @@ $RECYCLE.BIN/
 
 # MikroORM
 temp/**
+migrations/*.json
 
 # End of https://www.toptal.com/developers/gitignore/api/node,jetbrains+all,visualstudiocode,macos,windows
\ No newline at end of file
diff --git a/migrations/Migration20241225000904.ts b/migrations/Migration20241225000904.ts
new file mode 100644
index 0000000..60927e9
--- /dev/null
+++ b/migrations/Migration20241225000904.ts
@@ -0,0 +1,76 @@
+import { Migration } from '@mikro-orm/migrations';
+
+export class Migration20241225000904 extends Migration {
+
+  override async up(): Promise<void> {
+    this.addSql(`create table \`sprite\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
+
+    this.addSql(`create table \`item\` (\`id\` varchar(255) not null, \`name\` varchar(255) not null, \`description\` varchar(255) null, \`item_type\` ItemType not null, \`stackable\` tinyint(1) not null default false, \`rarity\` varchar(255) not null default 'COMMON', \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`item\` add index \`item_sprite_id_index\`(\`sprite_id\`);`);
+
+    this.addSql(`create table \`character_type\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`gender\` CharacterGender not null, \`race\` CharacterRace not null, \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null, \`created_at\` datetime not null, \`updated_at\` datetime not null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`character_type\` add index \`character_type_sprite_id_index\`(\`sprite_id\`);`);
+
+    this.addSql(`create table \`character_hair\` (\`id\` int unsigned not null auto_increment primary key, \`name\` varchar(255) not null, \`gender\` varchar(255) not null default 'MALE', \`is_selectable\` tinyint(1) not null default false, \`sprite_id\` varchar(255) null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`character_hair\` add index \`character_hair_sprite_id_index\`(\`sprite_id\`);`);
+
+    this.addSql(`create table \`sprite_action\` (\`id\` varchar(255) not null, \`sprite_id\` varchar(255) not null, \`action\` varchar(255) not null, \`sprites\` json null, \`origin_x\` int not null default 0, \`origin_y\` int not null default 0, \`is_animated\` tinyint(1) not null default false, \`is_looping\` tinyint(1) not null default false, \`frame_width\` int not null default 0, \`frame_height\` int not null default 0, \`frame_rate\` int not null default 0, primary key (\`id\`)) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`sprite_action\` add index \`sprite_action_sprite_id_index\`(\`sprite_id\`);`);
+
+    this.addSql(`create table \`user\` (\`id\` int unsigned not null auto_increment primary key, \`username\` varchar(255) not null, \`email\` varchar(255) not null, \`password\` varchar(255) not null, \`online\` tinyint(1) not null default false) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`user\` add unique \`user_username_unique\`(\`username\`);`);
+    this.addSql(`alter table \`user\` add unique \`user_email_unique\`(\`email\`);`);
+
+    this.addSql(`create table \`password_reset_token\` (\`id\` int unsigned not null auto_increment primary key, \`user_id\` int unsigned not null, \`token\` varchar(255) not null, \`created_at\` datetime not null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`password_reset_token\` add index \`password_reset_token_user_id_index\`(\`user_id\`);`);
+    this.addSql(`alter table \`password_reset_token\` add unique \`password_reset_token_token_unique\`(\`token\`);`);
+
+    this.addSql(`create table \`world\` (\`date\` datetime not null, \`is_rain_enabled\` tinyint(1) not null default false, \`rain_percentage\` int not null default 0, \`is_fog_enabled\` tinyint(1) not null default false, \`fog_density\` int not null default 0, primary key (\`date\`)) default character set utf8mb4 engine = InnoDB;`);
+
+    this.addSql(`create table \`zone\` (\`id\` int unsigned not null auto_increment primary key) default character set utf8mb4 engine = InnoDB;`);
+
+    this.addSql(`create table \`character\` (\`id\` int unsigned not null auto_increment primary key, \`user_id\` int unsigned not null, \`name\` varchar(255) not null, \`online\` tinyint(1) not null default false, \`role\` varchar(255) not null default 'player', \`zone_id\` int unsigned not null, \`position_x\` int not null default 0, \`position_y\` int not null default 0, \`rotation\` int not null default 0, \`character_type_id\` int unsigned null, \`character_hair_id\` int unsigned null, \`alignment\` int not null default 50, \`hitpoints\` int not null default 100, \`mana\` int not null default 100, \`level\` int not null default 1, \`experience\` int not null default 0, \`strength\` int not null default 10, \`dexterity\` int not null default 10, \`intelligence\` int not null default 10, \`wisdom\` int not null default 10) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`character\` add index \`character_user_id_index\`(\`user_id\`);`);
+    this.addSql(`alter table \`character\` add unique \`character_name_unique\`(\`name\`);`);
+    this.addSql(`alter table \`character\` add index \`character_zone_id_index\`(\`zone_id\`);`);
+    this.addSql(`alter table \`character\` add index \`character_character_type_id_index\`(\`character_type_id\`);`);
+    this.addSql(`alter table \`character\` add index \`character_character_hair_id_index\`(\`character_hair_id\`);`);
+
+    this.addSql(`create table \`chat\` (\`id\` int unsigned not null auto_increment primary key, \`character_id\` int unsigned not null, \`zone_id\` int unsigned not null, \`message\` varchar(255) not null, \`created_at\` datetime not null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`chat\` add index \`chat_character_id_index\`(\`character_id\`);`);
+    this.addSql(`alter table \`chat\` add index \`chat_zone_id_index\`(\`zone_id\`);`);
+
+    this.addSql(`create table \`character_item\` (\`id\` int unsigned not null auto_increment primary key, \`character_id\` int unsigned not null, \`item_id\` varchar(255) not null, \`quantity\` int not null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`character_item\` add index \`character_item_character_id_index\`(\`character_id\`);`);
+    this.addSql(`alter table \`character_item\` add index \`character_item_item_id_index\`(\`item_id\`);`);
+
+    this.addSql(`create table \`character_equipment\` (\`id\` int unsigned not null auto_increment primary key, \`slot\` CharacterEquipmentSlotType not null, \`character_id\` int unsigned not null, \`character_item_id\` int unsigned not null) default character set utf8mb4 engine = InnoDB;`);
+    this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_id_index\`(\`character_id\`);`);
+    this.addSql(`alter table \`character_equipment\` add index \`character_equipment_character_item_id_index\`(\`character_item_id\`);`);
+
+    this.addSql(`alter table \`item\` add constraint \`item_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`);
+
+    this.addSql(`alter table \`character_type\` add constraint \`character_type_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`);
+
+    this.addSql(`alter table \`character_hair\` add constraint \`character_hair_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade on delete set null;`);
+
+    this.addSql(`alter table \`sprite_action\` add constraint \`sprite_action_sprite_id_foreign\` foreign key (\`sprite_id\`) references \`sprite\` (\`id\`) on update cascade;`);
+
+    this.addSql(`alter table \`password_reset_token\` add constraint \`password_reset_token_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade;`);
+
+    this.addSql(`alter table \`character\` add constraint \`character_user_id_foreign\` foreign key (\`user_id\`) references \`user\` (\`id\`) on update cascade;`);
+    this.addSql(`alter table \`character\` add constraint \`character_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade;`);
+    this.addSql(`alter table \`character\` add constraint \`character_character_type_id_foreign\` foreign key (\`character_type_id\`) references \`character_type\` (\`id\`) on update cascade on delete set null;`);
+    this.addSql(`alter table \`character\` add constraint \`character_character_hair_id_foreign\` foreign key (\`character_hair_id\`) references \`character_hair\` (\`id\`) on update cascade on delete set null;`);
+
+    this.addSql(`alter table \`chat\` add constraint \`chat_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade;`);
+    this.addSql(`alter table \`chat\` add constraint \`chat_zone_id_foreign\` foreign key (\`zone_id\`) references \`zone\` (\`id\`) on update cascade;`);
+
+    this.addSql(`alter table \`character_item\` add constraint \`character_item_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade;`);
+    this.addSql(`alter table \`character_item\` add constraint \`character_item_item_id_foreign\` foreign key (\`item_id\`) references \`item\` (\`id\`) on update cascade;`);
+
+    this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_id_foreign\` foreign key (\`character_id\`) references \`character\` (\`id\`) on update cascade;`);
+    this.addSql(`alter table \`character_equipment\` add constraint \`character_equipment_character_item_id_foreign\` foreign key (\`character_item_id\`) references \`character_item\` (\`id\`) on update cascade;`);
+  }
+
+}
diff --git a/mikro-orm.config.ts b/mikro-orm.config.ts
new file mode 100644
index 0000000..ecf8c5f
--- /dev/null
+++ b/mikro-orm.config.ts
@@ -0,0 +1,26 @@
+// import { defineConfig, MariaDbDriver } from '@mikro-orm/mariadb'
+import { defineConfig, MySqlDriver } from '@mikro-orm/mysql'
+import { Migrator } from '@mikro-orm/migrations'
+import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
+import serverConfig from './src/utilities/config'
+
+export default defineConfig({
+  extensions: [Migrator],
+  metadataProvider: TsMorphMetadataProvider,
+  entities: ['./src/entities/**/*.js'],
+  entitiesTs: ['./src/entities/**/*.ts'],
+  driver: MySqlDriver,
+  host: serverConfig.DB_HOST,
+  port: serverConfig.DB_PORT,
+  user: serverConfig.DB_USER,
+  password: serverConfig.DB_PASS,
+  dbName: serverConfig.DB_NAME,
+  debug: serverConfig.ENV !== 'production',
+  driverOptions: {
+    allowPublicKeyRetrieval: true
+  },
+  migrations: {
+    path: './migrations',
+    pathTs: './migrations',
+  }
+})
\ No newline at end of file
diff --git a/src/server.ts b/src/server.ts
index cc01549..9c9450f 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -11,12 +11,12 @@ import { TSocket } from '#utilities/types'
 import { Database } from '#utilities/database'
 import prisma from '#utilities/prisma' // @TODO: Remove this
 import { appLogger, watchLogs } from '#utilities/logger'
-import ZoneManager from './managers/zoneManager'
-import UserManager from './managers/userManager'
-import CommandManager from './managers/commandManager'
-import QueueManager from './managers/queueManager'
-import DateManager from './managers/dateManager'
-import WeatherManager from './managers/weatherManager'
+import ZoneManager from '#managers/zoneManager'
+import UserManager from '#managers/userManager'
+import CommandManager from '#managers/commandManager'
+import QueueManager from '#managers/queueManager'
+import DateManager from '#managers/dateManager'
+import WeatherManager from '#managers/weatherManager'
 
 export class Server {
   private readonly app: Application
diff --git a/src/utilities/database.ts b/src/utilities/database.ts
index 91a5d2e..6340cb2 100644
--- a/src/utilities/database.ts
+++ b/src/utilities/database.ts
@@ -1,7 +1,5 @@
-import { MariaDbDriver, MikroORM } from '@mikro-orm/mariadb'
-import { Migrator } from '@mikro-orm/migrations'
-import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
-import config from '#utilities/config'
+import config from '../../mikro-orm.config'
+import { MikroORM } from '@mikro-orm/mariadb'
 import { appLogger } from '#utilities/logger'
 
 /**
@@ -12,22 +10,7 @@ export class Database {
 
   private static async init(): Promise<MikroORM> {
     try {
-      const orm = await MikroORM.init({
-        extensions: [Migrator],
-        metadataProvider: TsMorphMetadataProvider,
-        entities: ['./src/entities/**/*.js'],
-        entitiesTs: ['./src/entities/**/*.ts'],
-        driver: MariaDbDriver,
-        dbName: config.DB_NAME,
-        host: config.DB_HOST,
-        port: config.DB_PORT,
-        user: config.DB_USER,
-        password: config.DB_PASS,
-        debug: config.ENV !== 'production',
-        driverOptions: {
-          allowPublicKeyRetrieval: true
-        }
-      })
+      const orm = await MikroORM.init(config)
       appLogger.info('MikroORM connected successfully')
       return orm
     } catch (error) {