summaryrefslogtreecommitdiff
path: root/apps/web/src/project/transfer/migrate.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/project/transfer/migrate.ts')
-rw-r--r--apps/web/src/project/transfer/migrate.ts75
1 files changed, 75 insertions, 0 deletions
diff --git a/apps/web/src/project/transfer/migrate.ts b/apps/web/src/project/transfer/migrate.ts
new file mode 100644
index 00000000..14f59790
--- /dev/null
+++ b/apps/web/src/project/transfer/migrate.ts
@@ -0,0 +1,75 @@
+import type { StorageMigration } from "@/services/storage/migrations/base";
+import type { ProjectRecord } from "@/services/storage/migrations/transformers/types";
+import { getProjectId } from "@/services/storage/migrations/transformers/utils";
+
+/**
+ * In-memory counterpart to `runStorageMigrations`: applies the same migration
+ * registry to a single project record (e.g. parsed from an imported project
+ * archive) without touching IndexedDB.
+ */
+
+export function getRecordVersion({
+ project,
+}: {
+ project: ProjectRecord;
+}): number {
+ const versionValue = project.version;
+ if (typeof versionValue === "number") {
+ return versionValue;
+ }
+
+ const scenesValue = project.scenes;
+ if (Array.isArray(scenesValue) && scenesValue.length > 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+export interface MigratedProjectRecord {
+ project: ProjectRecord;
+ fromVersion: number;
+ toVersion: number;
+ complete: boolean;
+}
+
+export async function migrateProjectRecord({
+ project,
+ migrations,
+}: {
+ project: ProjectRecord;
+ migrations: StorageMigration[];
+}): Promise<MigratedProjectRecord> {
+ const orderedMigrations = [...migrations].sort((a, b) => a.from - b.from);
+ const fromVersion = getRecordVersion({ project });
+ const targetVersion = orderedMigrations.at(-1)?.to ?? fromVersion;
+
+ let currentVersion = fromVersion;
+ let record = project;
+ const projectId = getProjectId({ project: record }) ?? "imported-project";
+
+ for (const migration of orderedMigrations) {
+ if (migration.from !== currentVersion) {
+ continue;
+ }
+
+ const result = await migration.run({
+ projectId,
+ project: record,
+ });
+
+ if (result.skipped) {
+ break;
+ }
+
+ record = result.project;
+ currentVersion = migration.to;
+ }
+
+ return {
+ project: record,
+ fromVersion,
+ toVersion: currentVersion,
+ complete: currentVersion >= targetVersion,
+ };
+}