From 34e2392b489d5e3250ceecc360f54104ec014f97 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:39:19 +0200 Subject: [PATCH] :sparkles: automatically run db migrations --- .../migrate_db_engine.js | 0 util/src/entities/Migration.ts | 18 +++++ util/src/entities/index.ts | 1 + .../migrations/1633881705509-VanityInvite.ts | 2 + util/src/migrations/1634308884591-Stickers.ts | 66 +++++++++++++++++++ util/src/util/Database.ts | 20 +++++- 6 files changed, 106 insertions(+), 1 deletion(-) rename util/{src/migrations => scripts}/migrate_db_engine.js (100%) create mode 100644 util/src/entities/Migration.ts create mode 100644 util/src/migrations/1634308884591-Stickers.ts diff --git a/util/src/migrations/migrate_db_engine.js b/util/scripts/migrate_db_engine.js similarity index 100% rename from util/src/migrations/migrate_db_engine.js rename to util/scripts/migrate_db_engine.js diff --git a/util/src/entities/Migration.ts b/util/src/entities/Migration.ts new file mode 100644 index 00000000..09df70fb --- /dev/null +++ b/util/src/entities/Migration.ts @@ -0,0 +1,18 @@ +import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm"; +import { BaseClassWithoutId } from "."; + +export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") + ? ObjectIdColumn + : PrimaryGeneratedColumn; + +@Entity("migrations") +export class Migration extends BaseClassWithoutId { + @PrimaryIdAutoGenerated() + id: number; + + @Column() + timestamp: number; + + @Column() + name: string; +} diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts index 31afed88..b52841c9 100644 --- a/util/src/entities/index.ts +++ b/util/src/entities/index.ts @@ -11,6 +11,7 @@ export * from "./Guild"; export * from "./Invite"; export * from "./Member"; export * from "./Message"; +export * from "./Migration"; export * from "./RateLimit"; export * from "./ReadState"; export * from "./Recipient"; diff --git a/util/src/migrations/1633881705509-VanityInvite.ts b/util/src/migrations/1633881705509-VanityInvite.ts index af9b98ae..45485310 100644 --- a/util/src/migrations/1633881705509-VanityInvite.ts +++ b/util/src/migrations/1633881705509-VanityInvite.ts @@ -1,6 +1,8 @@ import { MigrationInterface, QueryRunner } from "typeorm"; export class VanityInvite1633881705509 implements MigrationInterface { + name = "VanityInvite1633881705509"; + public async up(queryRunner: QueryRunner): Promise { try { await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`); diff --git a/util/src/migrations/1634308884591-Stickers.ts b/util/src/migrations/1634308884591-Stickers.ts new file mode 100644 index 00000000..fbc4649f --- /dev/null +++ b/util/src/migrations/1634308884591-Stickers.ts @@ -0,0 +1,66 @@ +import { MigrationInterface, QueryRunner, Table, TableColumn, TableForeignKey } from "typeorm"; + +export class Stickers1634308884591 implements MigrationInterface { + name = "Stickers1634308884591"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.dropForeignKey("read_states", "FK_6f255d873cfbfd7a93849b7ff74"); + await queryRunner.changeColumn( + "stickers", + "tags", + new TableColumn({ name: "tags", type: "varchar", isNullable: true }) + ); + await queryRunner.changeColumn( + "stickers", + "pack_id", + new TableColumn({ name: "pack_id", type: "varchar", isNullable: true }) + ); + await queryRunner.changeColumn("stickers", "type", new TableColumn({ name: "type", type: "integer" })); + await queryRunner.changeColumn( + "stickers", + "format_type", + new TableColumn({ name: "format_type", type: "integer" }) + ); + await queryRunner.changeColumn( + "stickers", + "available", + new TableColumn({ name: "available", type: "boolean", isNullable: true }) + ); + await queryRunner.changeColumn( + "stickers", + "user_id", + new TableColumn({ name: "user_id", type: "boolean", isNullable: true }) + ); + await queryRunner.createForeignKey( + "stickers", + new TableForeignKey({ + name: "FK_8f4ee73f2bb2325ff980502e158", + columnNames: ["user_id"], + referencedColumnNames: ["id"], + referencedTableName: "users", + onDelete: "CASCADE", + }) + ); + await queryRunner.createTable( + new Table({ + name: "sticker_packs", + columns: [ + new TableColumn({ name: "id", type: "varchar", isPrimary: true }), + new TableColumn({ name: "name", type: "varchar" }), + new TableColumn({ name: "description", type: "varchar", isNullable: true }), + new TableColumn({ name: "banner_asset_id", type: "varchar", isNullable: true }), + new TableColumn({ name: "cover_sticker_id", type: "varchar", isNullable: true }), + ], + foreignKeys: [ + new TableForeignKey({ + columnNames: ["cover_sticker_id"], + referencedColumnNames: ["id"], + referencedTableName: "stickers", + }), + ], + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise {} +} diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index 8bce3a6f..6124ffab 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -2,6 +2,7 @@ import path from "path"; import "reflect-metadata"; import { Connection, createConnection } from "typeorm"; import * as Models from "../entities"; +import { Migration } from "../entities/Migration"; import { yellow, green } from "nanocolors"; // UUID extension option is only supported with postgres @@ -33,10 +34,27 @@ export function initDatabase(): Promise { bigNumberStrings: false, supportBigNumbers: true, name: "default", + migrations: [path.join(__dirname, "..", "migrations", "*.js")], }); - promise.then((connection) => { + promise.then(async (connection: Connection) => { dbConnection = connection; + + // run migrations, and if it is a new fresh database, set it to the last migration + if (connection.migrations.length) { + if (!(await Migration.findOne({}))) { + let i = 0; + + await Migration.insert( + connection.migrations.map((x) => ({ + id: i++, + name: x.name, + timestamp: Date.now(), + })) + ); + } + } + await connection.runMigrations(); console.log(`[Database] ${green("connected")}`); });