diff --git a/.prettierignore b/.prettierignore index 05d298a1..9b6e9df6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,4 @@ pnpm-lock.yaml LICENSE.md tsconfig.json tsconfig.*.json +src/main/migrations diff --git a/src/main/data-source.ts b/src/main/data-source.ts index a88a8883..446ccbdc 100644 --- a/src/main/data-source.ts +++ b/src/main/data-source.ts @@ -8,30 +8,22 @@ import { UserPreferences, UserAuth, } from "@main/entity"; -import type { BetterSqlite3ConnectionOptions } from "typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions"; import { databasePath } from "./constants"; -import migrations from "./migrations"; +import * as migrations from "./migrations"; -export const createDataSource = ( - options: Partial -) => - new DataSource({ - type: "better-sqlite3", - entities: [ - Game, - Repack, - UserPreferences, - GameShopCache, - DownloadSource, - DownloadQueue, - UserAuth, - ], - synchronize: true, - database: databasePath, - ...options, - }); - -export const dataSource = createDataSource({ +export const dataSource = new DataSource({ + type: "better-sqlite3", + entities: [ + Game, + Repack, + UserPreferences, + GameShopCache, + DownloadSource, + DownloadQueue, + UserAuth, + ], + synchronize: true, + database: databasePath, migrations, }); diff --git a/src/main/migrations/1715900413313-fix_repack_uploadDate.ts b/src/main/migrations/1715900413313-fix_repack_uploadDate.ts deleted file mode 100644 index e9d0a6c2..00000000 --- a/src/main/migrations/1715900413313-fix_repack_uploadDate.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class FixRepackUploadDate1715900413313 implements MigrationInterface { - public async up(_: QueryRunner): Promise { - return; - } - - public async down(_: QueryRunner): Promise { - return; - } -} diff --git a/src/main/migrations/1716776027208-alter_lastTimePlayed_to_datime.ts b/src/main/migrations/1716776027208-alter_lastTimePlayed_to_datime.ts deleted file mode 100644 index 6a562915..00000000 --- a/src/main/migrations/1716776027208-alter_lastTimePlayed_to_datime.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Game } from "@main/entity"; -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class AlterLastTimePlayedToDatime1716776027208 - implements MigrationInterface -{ - public async up(queryRunner: QueryRunner): Promise { - // 2024-05-27 02:08:17 - // Mon, 27 May 2024 02:08:17 GMT - const updateLastTimePlayedValues = ` - UPDATE game SET lastTimePlayed = (SELECT - SUBSTR(lastTimePlayed, 13, 4) || '-' || -- Year - CASE SUBSTR(lastTimePlayed, 9, 3) - WHEN 'Jan' THEN '01' - WHEN 'Feb' THEN '02' - WHEN 'Mar' THEN '03' - WHEN 'Apr' THEN '04' - WHEN 'May' THEN '05' - WHEN 'Jun' THEN '06' - WHEN 'Jul' THEN '07' - WHEN 'Aug' THEN '08' - WHEN 'Sep' THEN '09' - WHEN 'Oct' THEN '10' - WHEN 'Nov' THEN '11' - WHEN 'Dec' THEN '12' - END || '-' || -- Month - SUBSTR(lastTimePlayed, 6, 2) || ' ' || -- Day - SUBSTR(lastTimePlayed, 18, 8) -- hh:mm:ss; - FROM game) - WHERE lastTimePlayed IS NOT NULL; - `; - - await queryRunner.query(updateLastTimePlayedValues); - } - - public async down(queryRunner: QueryRunner): Promise { - const queryBuilder = queryRunner.manager.createQueryBuilder(Game, "game"); - - const result = await queryBuilder.getMany(); - - for (const game of result) { - if (!game.lastTimePlayed) continue; - await queryRunner.query( - `UPDATE game set lastTimePlayed = ? WHERE id = ?;`, - [game.lastTimePlayed.toUTCString(), game.id] - ); - } - } -} diff --git a/src/main/migrations/1724081695967-Hydra_2_0_3.ts b/src/main/migrations/1724081695967-Hydra_2_0_3.ts new file mode 100644 index 00000000..5ab18acb --- /dev/null +++ b/src/main/migrations/1724081695967-Hydra_2_0_3.ts @@ -0,0 +1,50 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Hydra2031724081695967 implements MigrationInterface { + name = 'Hydra2031724081695967' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "game" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "objectID" text NOT NULL, "remoteId" text, "title" text NOT NULL, "iconUrl" text, "folderName" text, "downloadPath" text, "executablePath" text, "playTimeInMilliseconds" integer NOT NULL DEFAULT (0), "shop" text NOT NULL, "status" text, "downloader" integer NOT NULL DEFAULT (1), "progress" float NOT NULL DEFAULT (0), "bytesDownloaded" integer NOT NULL DEFAULT (0), "lastTimePlayed" datetime, "fileSize" float NOT NULL DEFAULT (0), "uri" text, "isDeleted" boolean NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "repackId" integer, CONSTRAINT "UQ_04293f46e8db3deaec8dfb69264" UNIQUE ("objectID"), CONSTRAINT "UQ_6dac8c3148e141251a4864e94d4" UNIQUE ("remoteId"), CONSTRAINT "REL_0c1d6445ad047d9bbd256f961f" UNIQUE ("repackId"))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "download_source" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "url" text, "name" text NOT NULL, "etag" text, "downloadCount" integer NOT NULL DEFAULT (0), "status" text NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), CONSTRAINT "UQ_aec2879321a87e9bb2ed477981a" UNIQUE ("url"))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "repack" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" text NOT NULL, "magnet" text NOT NULL, "page" integer, "repacker" text NOT NULL, "fileSize" text NOT NULL, "uploadDate" datetime NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "downloadSourceId" integer, CONSTRAINT "UQ_a46a68496754a4d429ddf9d48ec" UNIQUE ("title"), CONSTRAINT "UQ_5e8d57798643e693bced32095d2" UNIQUE ("magnet"))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "user_preferences" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "downloadsPath" text, "language" text NOT NULL DEFAULT ('en'), "realDebridApiToken" text, "downloadNotificationsEnabled" boolean NOT NULL DEFAULT (0), "repackUpdatesNotificationsEnabled" boolean NOT NULL DEFAULT (0), "preferQuitInsteadOfHiding" boolean NOT NULL DEFAULT (0), "runAtStartup" boolean NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "game_shop_cache" ("objectID" text PRIMARY KEY NOT NULL, "shop" text NOT NULL, "serializedData" text, "howLongToBeatSerializedData" text, "language" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "download_queue" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "gameId" integer, CONSTRAINT "REL_aed852c94d9ded617a7a07f541" UNIQUE ("gameId"))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "user_auth" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "userId" text NOT NULL DEFAULT (''), "displayName" text NOT NULL DEFAULT (''), "profileImageUrl" text, "accessToken" text NOT NULL DEFAULT (''), "refreshToken" text NOT NULL DEFAULT (''), "tokenExpirationTimestamp" integer NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')))`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "temporary_game" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "objectID" text NOT NULL, "remoteId" text, "title" text NOT NULL, "iconUrl" text, "folderName" text, "downloadPath" text, "executablePath" text, "playTimeInMilliseconds" integer NOT NULL DEFAULT (0), "shop" text NOT NULL, "status" text, "downloader" integer NOT NULL DEFAULT (1), "progress" float NOT NULL DEFAULT (0), "bytesDownloaded" integer NOT NULL DEFAULT (0), "lastTimePlayed" datetime, "fileSize" float NOT NULL DEFAULT (0), "uri" text, "isDeleted" boolean NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "repackId" integer, CONSTRAINT "UQ_04293f46e8db3deaec8dfb69264" UNIQUE ("objectID"), CONSTRAINT "UQ_6dac8c3148e141251a4864e94d4" UNIQUE ("remoteId"), CONSTRAINT "REL_0c1d6445ad047d9bbd256f961f" UNIQUE ("repackId"), CONSTRAINT "FK_0c1d6445ad047d9bbd256f961f6" FOREIGN KEY ("repackId") REFERENCES "repack" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_game"("id", "objectID", "remoteId", "title", "iconUrl", "folderName", "downloadPath", "executablePath", "playTimeInMilliseconds", "shop", "status", "downloader", "progress", "bytesDownloaded", "lastTimePlayed", "fileSize", "uri", "isDeleted", "createdAt", "updatedAt", "repackId") SELECT "id", "objectID", "remoteId", "title", "iconUrl", "folderName", "downloadPath", "executablePath", "playTimeInMilliseconds", "shop", "status", "downloader", "progress", "bytesDownloaded", "lastTimePlayed", "fileSize", "uri", "isDeleted", "createdAt", "updatedAt", "repackId" FROM "game"`); + await queryRunner.query(`DROP TABLE "game"`); + await queryRunner.query(`ALTER TABLE "temporary_game" RENAME TO "game"`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "temporary_repack" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" text NOT NULL, "magnet" text NOT NULL, "page" integer, "repacker" text NOT NULL, "fileSize" text NOT NULL, "uploadDate" datetime NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "downloadSourceId" integer, CONSTRAINT "UQ_a46a68496754a4d429ddf9d48ec" UNIQUE ("title"), CONSTRAINT "UQ_5e8d57798643e693bced32095d2" UNIQUE ("magnet"), CONSTRAINT "FK_13f131029be1dd361fd3cd9c2a6" FOREIGN KEY ("downloadSourceId") REFERENCES "download_source" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_repack"("id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId") SELECT "id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId" FROM "repack"`); + await queryRunner.query(`DROP TABLE "repack"`); + await queryRunner.query(`ALTER TABLE "temporary_repack" RENAME TO "repack"`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "temporary_download_queue" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "gameId" integer, CONSTRAINT "REL_aed852c94d9ded617a7a07f541" UNIQUE ("gameId"), CONSTRAINT "FK_aed852c94d9ded617a7a07f5415" FOREIGN KEY ("gameId") REFERENCES "game" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_download_queue"("id", "createdAt", "updatedAt", "gameId") SELECT "id", "createdAt", "updatedAt", "gameId" FROM "download_queue"`); + await queryRunner.query(`DROP TABLE "download_queue"`); + await queryRunner.query(`ALTER TABLE "temporary_download_queue" RENAME TO "download_queue"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "download_queue" RENAME TO "temporary_download_queue"`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "download_queue" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "gameId" integer, CONSTRAINT "REL_aed852c94d9ded617a7a07f541" UNIQUE ("gameId"))`); + await queryRunner.query(`INSERT INTO "download_queue"("id", "createdAt", "updatedAt", "gameId") SELECT "id", "createdAt", "updatedAt", "gameId" FROM "temporary_download_queue"`); + await queryRunner.query(`DROP TABLE "temporary_download_queue"`); + await queryRunner.query(`ALTER TABLE "repack" RENAME TO "temporary_repack"`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "repack" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" text NOT NULL, "magnet" text NOT NULL, "page" integer, "repacker" text NOT NULL, "fileSize" text NOT NULL, "uploadDate" datetime NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "downloadSourceId" integer, CONSTRAINT "UQ_a46a68496754a4d429ddf9d48ec" UNIQUE ("title"), CONSTRAINT "UQ_5e8d57798643e693bced32095d2" UNIQUE ("magnet"))`); + await queryRunner.query(`INSERT INTO "repack"("id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId") SELECT "id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId" FROM "temporary_repack"`); + await queryRunner.query(`DROP TABLE "temporary_repack"`); + await queryRunner.query(`ALTER TABLE "game" RENAME TO "temporary_game"`); + await queryRunner.query(`CREATE TABLE IF NOT EXISTS "game" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "objectID" text NOT NULL, "remoteId" text, "title" text NOT NULL, "iconUrl" text, "folderName" text, "downloadPath" text, "executablePath" text, "playTimeInMilliseconds" integer NOT NULL DEFAULT (0), "shop" text NOT NULL, "status" text, "downloader" integer NOT NULL DEFAULT (1), "progress" float NOT NULL DEFAULT (0), "bytesDownloaded" integer NOT NULL DEFAULT (0), "lastTimePlayed" datetime, "fileSize" float NOT NULL DEFAULT (0), "uri" text, "isDeleted" boolean NOT NULL DEFAULT (0), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "repackId" integer, CONSTRAINT "UQ_04293f46e8db3deaec8dfb69264" UNIQUE ("objectID"), CONSTRAINT "UQ_6dac8c3148e141251a4864e94d4" UNIQUE ("remoteId"), CONSTRAINT "REL_0c1d6445ad047d9bbd256f961f" UNIQUE ("repackId"))`); + await queryRunner.query(`INSERT INTO "game"("id", "objectID", "remoteId", "title", "iconUrl", "folderName", "downloadPath", "executablePath", "playTimeInMilliseconds", "shop", "status", "downloader", "progress", "bytesDownloaded", "lastTimePlayed", "fileSize", "uri", "isDeleted", "createdAt", "updatedAt", "repackId") SELECT "id", "objectID", "remoteId", "title", "iconUrl", "folderName", "downloadPath", "executablePath", "playTimeInMilliseconds", "shop", "status", "downloader", "progress", "bytesDownloaded", "lastTimePlayed", "fileSize", "uri", "isDeleted", "createdAt", "updatedAt", "repackId" FROM "temporary_game"`); + await queryRunner.query(`DROP TABLE "temporary_game"`); + await queryRunner.query(`DROP TABLE "user_auth"`); + await queryRunner.query(`DROP TABLE "download_queue"`); + await queryRunner.query(`DROP TABLE "game_shop_cache"`); + await queryRunner.query(`DROP TABLE "user_preferences"`); + await queryRunner.query(`DROP TABLE "repack"`); + await queryRunner.query(`DROP TABLE "download_source"`); + await queryRunner.query(`DROP TABLE "game"`); + } + +} diff --git a/src/main/migrations/1724081984535-DowloadsRefactor.ts b/src/main/migrations/1724081984535-DowloadsRefactor.ts new file mode 100644 index 00000000..3afc8444 --- /dev/null +++ b/src/main/migrations/1724081984535-DowloadsRefactor.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DowloadsRefactor1724081984535 implements MigrationInterface { + name = 'DowloadsRefactor1724081984535' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "temporary_repack" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" text NOT NULL, "magnet" text NOT NULL, "page" integer, "repacker" text NOT NULL, "fileSize" text NOT NULL, "uploadDate" datetime NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "downloadSourceId" integer, "uris" text NOT NULL DEFAULT ('[]'), CONSTRAINT "UQ_5e8d57798643e693bced32095d2" UNIQUE ("magnet"), CONSTRAINT "UQ_a46a68496754a4d429ddf9d48ec" UNIQUE ("title"), CONSTRAINT "FK_13f131029be1dd361fd3cd9c2a6" FOREIGN KEY ("downloadSourceId") REFERENCES "download_source" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "temporary_repack"("id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId") SELECT "id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId" FROM "repack"`); + await queryRunner.query(`DROP TABLE "repack"`); + await queryRunner.query(`ALTER TABLE "temporary_repack" RENAME TO "repack"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "repack" RENAME TO "temporary_repack"`); + await queryRunner.query(`CREATE TABLE "repack" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" text NOT NULL, "magnet" text NOT NULL, "page" integer, "repacker" text NOT NULL, "fileSize" text NOT NULL, "uploadDate" datetime NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "downloadSourceId" integer, CONSTRAINT "UQ_5e8d57798643e693bced32095d2" UNIQUE ("magnet"), CONSTRAINT "UQ_a46a68496754a4d429ddf9d48ec" UNIQUE ("title"), CONSTRAINT "FK_13f131029be1dd361fd3cd9c2a6" FOREIGN KEY ("downloadSourceId") REFERENCES "download_source" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`); + await queryRunner.query(`INSERT INTO "repack"("id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId") SELECT "id", "title", "magnet", "page", "repacker", "fileSize", "uploadDate", "createdAt", "updatedAt", "downloadSourceId" FROM "temporary_repack"`); + await queryRunner.query(`DROP TABLE "temporary_repack"`); + } + +} diff --git a/src/main/migrations/index.ts b/src/main/migrations/index.ts index c0c96e45..5546bce0 100644 --- a/src/main/migrations/index.ts +++ b/src/main/migrations/index.ts @@ -1,7 +1,2 @@ -import { FixRepackUploadDate1715900413313 } from "./1715900413313-fix_repack_uploadDate"; -import { AlterLastTimePlayedToDatime1716776027208 } from "./1716776027208-alter_lastTimePlayed_to_datime"; - -export default [ - FixRepackUploadDate1715900413313, - AlterLastTimePlayedToDatime1716776027208, -]; +export * from "./1724081695967-Hydra_2_0_3"; +export * from "./1724081984535-DowloadsRefactor";