123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- import { migrate } from "drizzle-orm/better-sqlite3/migrator";
- import db, { exists } from "@server/db";
- import path from "path";
- import semver from "semver";
- import { versionMigrations } from "@server/db/schema";
- import { __DIRNAME, APP_PATH, APP_VERSION } from "@server/lib/consts";
- import { SqliteError } from "better-sqlite3";
- import fs from "fs";
- import m1 from "./scripts/1.0.0-beta1";
- import m2 from "./scripts/1.0.0-beta2";
- import m3 from "./scripts/1.0.0-beta3";
- import m4 from "./scripts/1.0.0-beta5";
- import m5 from "./scripts/1.0.0-beta6";
- import m6 from "./scripts/1.0.0-beta9";
- import m7 from "./scripts/1.0.0-beta10";
- import m8 from "./scripts/1.0.0-beta12";
- // THIS CANNOT IMPORT ANYTHING FROM THE SERVER
- // EXCEPT FOR THE DATABASE AND THE SCHEMA
- // Define the migration list with versions and their corresponding functions
- const migrations = [
- { version: "1.0.0-beta.1", run: m1 },
- { version: "1.0.0-beta.2", run: m2 },
- { version: "1.0.0-beta.3", run: m3 },
- { version: "1.0.0-beta.5", run: m4 },
- { version: "1.0.0-beta.6", run: m5 },
- { version: "1.0.0-beta.9", run: m6 },
- { version: "1.0.0-beta.10", run: m7 },
- { version: "1.0.0-beta.12", run: m8 }
- // Add new migrations here as they are created
- ] as const;
- await run();
- async function run() {
- // backup the database
- backupDb();
- // run the migrations
- await runMigrations();
- }
- function backupDb() {
- // make dir config/db/backups
- const appPath = APP_PATH;
- const dbDir = path.join(appPath, "db");
- const backupsDir = path.join(dbDir, "backups");
- // check if the backups directory exists and create it if it doesn't
- if (!fs.existsSync(backupsDir)) {
- fs.mkdirSync(backupsDir, { recursive: true });
- }
- // copy the db.sqlite file to backups
- // add the date to the filename
- const date = new Date();
- const dateString = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}_${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}`;
- const dbPath = path.join(dbDir, "db.sqlite");
- const backupPath = path.join(backupsDir, `db_${dateString}.sqlite`);
- fs.copyFileSync(dbPath, backupPath);
- }
- export async function runMigrations() {
- try {
- const appVersion = APP_VERSION;
- if (exists) {
- await executeScripts();
- } else {
- console.log("Running migrations...");
- try {
- migrate(db, {
- migrationsFolder: path.join(__DIRNAME, "init") // put here during the docker build
- });
- console.log("Migrations completed successfully.");
- } catch (error) {
- console.error("Error running migrations:", error);
- }
- await db
- .insert(versionMigrations)
- .values({
- version: appVersion,
- executedAt: Date.now()
- })
- .execute();
- }
- } catch (e) {
- console.error("Error running migrations:", e);
- await new Promise((resolve) =>
- setTimeout(resolve, 1000 * 60 * 60 * 24 * 1)
- );
- }
- }
- async function executeScripts() {
- try {
- // Get the last executed version from the database
- const lastExecuted = await db.select().from(versionMigrations);
- // Filter and sort migrations
- const pendingMigrations = lastExecuted
- .map((m) => m)
- .sort((a, b) => semver.compare(b.version, a.version));
- const startVersion = pendingMigrations[0]?.version ?? "0.0.0";
- console.log(`Starting migrations from version ${startVersion}`);
- const migrationsToRun = migrations.filter((migration) =>
- semver.gt(migration.version, startVersion)
- );
- console.log(
- "Migrations to run:",
- migrationsToRun.map((m) => m.version).join(", ")
- );
- // Run migrations in order
- for (const migration of migrationsToRun) {
- console.log(`Running migration ${migration.version}`);
- try {
- await migration.run();
- // Update version in database
- await db
- .insert(versionMigrations)
- .values({
- version: migration.version,
- executedAt: Date.now()
- })
- .execute();
- console.log(
- `Successfully completed migration ${migration.version}`
- );
- } catch (e) {
- if (
- e instanceof SqliteError &&
- e.code === "SQLITE_CONSTRAINT_UNIQUE"
- ) {
- console.error("Migration has already run! Skipping...");
- continue;
- }
- console.error(
- `Failed to run migration ${migration.version}:`,
- e
- );
- throw e; // Re-throw to stop migration process
- }
- }
- console.log("All migrations completed successfully");
- } catch (error) {
- console.error("Migration process failed:", error);
- throw error;
- }
- }
|