fix Capacitor to use the same migrations (migrations run but accounts aren't created)

This commit is contained in:
2025-06-04 22:01:14 -06:00
parent 705c6092a3
commit 8e57692387
6 changed files with 96 additions and 270 deletions

View File

@@ -1,6 +1,3 @@
import { logger } from "@/utils/logger";
import { QueryExecResult } from "../interfaces/database";
interface Migration {
name: string;
sql: string;
@@ -19,46 +16,55 @@ export class MigrationService {
return MigrationService.instance;
}
async registerMigration(migration: Migration): Promise<void> {
registerMigration(migration: Migration) {
this.migrations.push(migration);
}
async runMigrations(
sqlExec: (
sql: string,
params?: unknown[],
) => Promise<Array<QueryExecResult>>,
/**
* @param sqlExec - A function that executes a SQL statement and returns some update result
* @param sqlQuery - A function that executes a SQL query and returns the result in some format
* @param extractMigrationNames - A function that extracts the names (string array) from a "select name from migrations" query
*/
async runMigrations<T>(
// note that this does not take parameters because the Capacitor SQLite 'execute' is different
sqlExec: (sql: string) => Promise<unknown>,
sqlQuery: (sql: string) => Promise<T>,
extractMigrationNames: (result: T) => Set<string>,
): Promise<void> {
// eslint-disable-next-line no-console
console.log("Will run migrations");
// Create migrations table if it doesn't exist
await sqlExec(`
const result0 = await sqlExec(`
CREATE TABLE IF NOT EXISTS migrations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
// eslint-disable-next-line no-console
console.log("Created migrations table", JSON.stringify(result0));
// Get list of executed migrations
const result: QueryExecResult[] = await sqlExec(
"SELECT name FROM migrations;",
const result1: T = await sqlQuery("SELECT name FROM migrations;");
const executedMigrations = extractMigrationNames(result1);
// eslint-disable-next-line no-console
console.log(
"Executed migration select",
JSON.stringify(executedMigrations),
);
let executedMigrations: Set<unknown> = new Set();
// Even with that query, the QueryExecResult may be [] (which doesn't make sense to me).
if (result.length > 0) {
const singleResult = result[0];
executedMigrations = new Set(
singleResult.values.map((row: unknown[]) => row[0]),
);
}
// Run pending migrations in order
for (const migration of this.migrations) {
if (!executedMigrations.has(migration.name)) {
await sqlExec(migration.sql);
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
migration.name,
]);
logger.log(`Migration ${migration.name} executed successfully`);
const result2 = await sqlExec(migration.sql);
// eslint-disable-next-line no-console
console.log("Executed migration", JSON.stringify(result2));
const result3 = await sqlExec(
`INSERT INTO migrations (name) VALUES ('${migration.name}')`,
);
// eslint-disable-next-line no-console
console.log("Updated migrations table", JSON.stringify(result3));
}
}
}