diff --git a/libs/db/migrations/README.md b/libs/db/migrations/README.md index 8cd50c99..8b08b20f 100644 --- a/libs/db/migrations/README.md +++ b/libs/db/migrations/README.md @@ -37,6 +37,7 @@ erDiagram string type } Deity_Domain { + ulid id ulid deity_id ulid domain_id } diff --git a/libs/db/migrations/diagram.mmd b/libs/db/migrations/diagram.mmd index d86893d3..99853b60 100644 --- a/libs/db/migrations/diagram.mmd +++ b/libs/db/migrations/diagram.mmd @@ -28,6 +28,7 @@ erDiagram string type } Deity_Domain { + ulid id ulid deity_id ulid domain_id } diff --git a/libs/db/migrations/src/01H5TV87JJ3CE73WBGZZWQYBP4-convert-to-new-ulid-type.ts b/libs/db/migrations/src/01H5TV87JJ3CE73WBGZZWQYBP4-convert-to-new-ulid-type.ts new file mode 100644 index 00000000..2ec1df44 --- /dev/null +++ b/libs/db/migrations/src/01H5TV87JJ3CE73WBGZZWQYBP4-convert-to-new-ulid-type.ts @@ -0,0 +1,137 @@ +import { + AlterColumnBuilder, + AlterColumnBuilderCallback, + Kysely, + sql, +} from 'kysely'; + +const convertToUlid = ( + column: string +): [string, AlterColumnBuilderCallback] => [ + column, + (col: AlterColumnBuilder) => + col.setDataType(sql`ulid USING (${column}::ulid)`), +]; + +const setUlidDefault = ( + column: string +): [string, AlterColumnBuilderCallback] => [ + column, + (col: AlterColumnBuilder) => col.setDefault(sql`gen_ulid()`), +]; + +const migrateTableColumnToUlid = async ( + db: Kysely, + table: string, + column: string, + setDefault = false +): Promise => { + let command = db.schema + .alterTable(table) + .alterColumn(...convertToUlid(column)); + if (setDefault) { + command = command.alterColumn(...setUlidDefault(column)); + } + await command.execute(); +}; + +const recreateForeignKey = async ( + db: Kysely, + table: string, + column: string, + targetTable: string, + targetColumn: string +): Promise => { + await db.schema + .alterTable(table) + .addForeignKeyConstraint(`${table}_${column}_fkey`, [column], targetTable, [ + targetColumn, + ]) + .execute(); +}; + +export const up = async (db: Kysely): Promise => { + await sql`CREATE EXTENSION ulid;`.execute(db); + await db.schema + .alterTable('deity_domain') + .dropConstraint('deity_domain_deity_id_fkey') + .execute(); + await db.schema + .alterTable('deity_domain') + .dropConstraint('deity_domain_domain_id_fkey') + .execute(); + await migrateTableColumnToUlid(db, 'domain', 'id', true); + await migrateTableColumnToUlid(db, 'deity', 'id', true); + await migrateTableColumnToUlid(db, 'deity_domain', 'id', true); + await migrateTableColumnToUlid(db, 'deity_domain', 'deity_id'); + await migrateTableColumnToUlid(db, 'deity_domain', 'domain_id'); + await recreateForeignKey(db, 'deity_domain', 'deity_id', 'deity', 'id'); + await recreateForeignKey(db, 'deity_domain', 'domain_id', 'domain', 'id'); + await db.schema + .alterTable('deity') + .dropConstraint('deity_category_fkey') + .execute(); + await db.schema + .alterTable('detiy') + .dropConstraint('deity_location_fkey') + .execute(); + await migrateTableColumnToUlid(db, 'deity_category', 'id', true); + await migrateTableColumnToUlid(db, 'deity', 'category'); + await migrateTableColumnToUlid(db, 'deity', 'location'); + await recreateForeignKey(db, 'deity', 'category', 'deity_category', 'id'); + await migrateTableColumnToUlid(db, 'location', 'id', true); + await recreateForeignKey(db, 'deity', 'location', 'location', 'id'); + await db.schema + .alterTable('racial_ability') + .dropConstraint('racial_ability_race_id_fkey') + .execute(); + await migrateTableColumnToUlid(db, 'race', 'id', true); + await migrateTableColumnToUlid(db, 'racial_ability', 'id', true); + await migrateTableColumnToUlid(db, 'racial_ability', 'race_id'); + await recreateForeignKey(db, 'racial_ability', 'race_id', 'race', 'id'); + await db.schema + .alterTable('user_permission') + .dropConstraint('user_permission_role_id_fkey') + .execute(); + await db.schema + .alterTable('user_permission') + .dropConstraint('user_permission_user_id_fkey') + .execute(); + await db.schema + .alterTable('login_method') + .dropConstraint('login_method_user_id_fkey') + .execute(); + await db.schema + .alterTable('local_login') + .dropConstraint('local_login_login_method_id_fkey') + .execute(); + await migrateTableColumnToUlid(db, 'role', 'id', true); + await migrateTableColumnToUlid(db, 'local_login', 'id', true); + await migrateTableColumnToUlid(db, 'local_login', 'login_method_id'); + await migrateTableColumnToUlid(db, 'login_method', 'id', true); + await migrateTableColumnToUlid(db, 'login_method', 'user_id'); + await migrateTableColumnToUlid(db, 'user_account', 'id', true); + await migrateTableColumnToUlid(db, 'user_permission', 'id', true); + await migrateTableColumnToUlid(db, 'user_permission', 'user_id'); + await migrateTableColumnToUlid(db, 'user_permission', 'role_id'); + await recreateForeignKey(db, 'user_permission', 'role_id', 'role', 'id'); + await recreateForeignKey( + db, + 'user_permission', + 'user_id', + 'user_account', + 'id' + ); + await recreateForeignKey(db, 'login_method', 'user_id', 'user_account', 'id'); + await recreateForeignKey( + db, + 'local_login', + 'login_method_id', + 'login_method', + 'id' + ); +}; + +export const down = async (db: Kysely) => { + await sql`DROP EXTENSION ulid`.execute(db); +}; diff --git a/package.json b/package.json index 89f2a1c4..da436afb 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "argon2": "^0.30.3", "axios": "^1.0.0", "jotai": "^2.2.2", - "kysely": "^0.24.2", + "kysely": "^0.26.1", "nest-commander": "^3.9.0", "nest-cookies": "^1.3.0", "nodemailer": "^6.9.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f9bfec77..d4e0f313 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ dependencies: specifier: ^2.2.2 version: 2.2.2(react@18.2.0) kysely: - specifier: ^0.24.2 - version: 0.24.2 + specifier: ^0.26.1 + version: 0.26.1 nest-commander: specifier: ^3.9.0 version: 3.9.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(@types/inquirer@8.1.0) @@ -11705,8 +11705,8 @@ packages: engines: {node: '>= 8'} dev: true - /kysely@0.24.2: - resolution: {integrity: sha512-+7eaTJNUYm2yRq1x+lEOZc+78TO35dTZ9b0dh49+Z9CTt2byMSbMiOKpwPlOyCAaHD4kILkAYWYZNywFlmBwRA==} + /kysely@0.26.1: + resolution: {integrity: sha512-FVRomkdZofBu3O8SiwAOXrwbhPZZr8mBN5ZeUWyprH29jzvy6Inzqbd0IMmGxpd4rcOCL9HyyBNWBa8FBqDAdg==} engines: {node: '>=14.0.0'} dev: false