fix(backup): accept backups from older schema versions on restore

Validate only a baseline of tables present in every release since v0.1.0
(plus __drizzle_migrations) instead of the full current schema, so restore's
post-swap runMigrations() can bring older backups up to date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Opus 5.5 committed 2026-10-04 15:12:51 -04:00
1 parent d73529586b
commit 72d9f8f2d1
4 files changed
+85 -9

No files matched your search

+40
View File
@@ -1,5 +1,8 @@
import { describe, expect, test } from "vitest";
import { findMissingBackupTables, REQUIRED_BACKUP_TABLES } from "@sofa/db/backup-tables";
import { testClient } from "@sofa/test/db";
import { getBackupSource, isKnownBackup, isValidBackupFilename } from "../src/backup";
describe("getBackupSource", () => {
@@ -79,3 +82,40 @@ describe("isValidBackupFilename", () => {
expect(isValidBackupFilename("sofa-manual-2024..01-15-120000.db")).toBe(false);
});
});
function currentTableNames(): string[] {
return (
testClient.prepare("SELECT name FROM sqlite_master WHERE type='table'").all() as {
name: string;
}[]
).map((r) => r.name);
}
describe("findMissingBackupTables", () => {
test("accepts a fully migrated database (current schema)", () => {
expect(findMissingBackupTables(currentTableNames())).toEqual([]);
});
test("accepts a database from before v0.1.3 (no platformTmdbIds)", () => {
const names = currentTableNames().filter((n) => n !== "platformTmdbIds");
expect(findMissingBackupTables(names)).toEqual([]);
});
test("accepts a database from v0.1.0 (no platform tables)", () => {
const newer = new Set(["platformTmdbIds", "platforms", "titleAvailability", "userPlatforms"]);
const names = currentTableNames().filter((n) => !newer.has(n));
expect(findMissingBackupTables(names)).toEqual([]);
});
test("rejects a non-Sofa SQLite file", () => {
const missing = findMissingBackupTables(["foo"]);
expect(missing).toContain("user");
expect(missing).toContain("titles");
expect(missing).toContain("__drizzle_migrations");
});
test("every required backup table exists in the current schema", () => {
const current = currentTableNames();
expect(REQUIRED_BACKUP_TABLES.filter((t) => !current.includes(t))).toEqual([]);
});
});