diff options
Diffstat (limited to 'apps/web/src/services/storage')
4 files changed, 141 insertions, 14 deletions
diff --git a/apps/web/src/services/storage/migrations/index.ts b/apps/web/src/services/storage/migrations/index.ts index 9f0f3e0d..b7ee37f5 100644 --- a/apps/web/src/services/storage/migrations/index.ts +++ b/apps/web/src/services/storage/migrations/index.ts @@ -22,10 +22,11 @@ import { V19toV20Migration } from "./v19-to-v20"; import { V20toV21Migration } from "./v20-to-v21";
import { V21toV22Migration } from "./v21-to-v22";
import { V22toV23Migration } from "./v22-to-v23";
+import { V23toV24Migration } from "./v23-to-v24";
export { runStorageMigrations } from "./runner";
export type { MigrationProgress } from "./runner";
-export const CURRENT_PROJECT_VERSION = 23;
+export const CURRENT_PROJECT_VERSION = 24;
export const migrations = [
new V0toV1Migration(),
@@ -51,4 +52,5 @@ export const migrations = [ new V20toV21Migration(),
new V21toV22Migration(),
new V22toV23Migration(),
+ new V23toV24Migration(),
];
diff --git a/apps/web/src/services/storage/migrations/transformers/v23-to-v24.ts b/apps/web/src/services/storage/migrations/transformers/v23-to-v24.ts new file mode 100644 index 00000000..710d4dc1 --- /dev/null +++ b/apps/web/src/services/storage/migrations/transformers/v23-to-v24.ts @@ -0,0 +1,113 @@ +import type { MigrationResult, ProjectRecord } from "./types"; +import { getProjectId, isRecord } from "./utils"; + +export function transformProjectV23ToV24({ + project, +}: { + project: ProjectRecord; +}): MigrationResult<ProjectRecord> { + if (!getProjectId({ project })) { + return { project, skipped: true, reason: "no project id" }; + } + + const version = project.version; + if (typeof version !== "number") { + return { project, skipped: true, reason: "invalid version" }; + } + if (version >= 24) { + return { project, skipped: true, reason: "already v24" }; + } + if (version !== 23) { + return { project, skipped: true, reason: "not v23" }; + } + + return { + project: { + ...migrateProject({ project }), + version: 24, + }, + skipped: false, + }; +} + +function migrateProject({ + project, +}: { + project: ProjectRecord; +}): ProjectRecord { + if (!Array.isArray(project.scenes)) { + return project; + } + + return { + ...project, + scenes: project.scenes.map((scene) => migrateScene({ scene })), + }; +} + +function migrateScene({ scene }: { scene: unknown }): unknown { + if (!isRecord(scene) || !Array.isArray(scene.tracks)) { + return scene; + } + + const mainTrack = findMainTrack({ tracks: scene.tracks }); + if (!mainTrack) { + return scene; + } + + return { + ...scene, + tracks: { + overlay: scene.tracks + .filter((track) => track !== mainTrack) + .map((track) => migrateTrack({ track })) + .filter( + (track): track is ProjectRecord => + isRecord(track) && track.type !== "audio", + ), + main: migrateTrack({ track: mainTrack }), + audio: scene.tracks + .map((track) => migrateTrack({ track })) + .filter( + (track): track is ProjectRecord => + isRecord(track) && track.type === "audio", + ), + }, + }; +} + +function findMainTrack({ + tracks, +}: { + tracks: unknown[]; +}): ProjectRecord | null { + for (const track of tracks) { + if (!isRecord(track)) { + continue; + } + if (track.type === "video" && track.isMain === true) { + return track; + } + } + + for (const track of tracks) { + if (!isRecord(track)) { + continue; + } + if (track.type === "video") { + return track; + } + } + + return null; +} + +function migrateTrack({ track }: { track: unknown }): unknown { + if (!isRecord(track)) { + return track; + } + + const nextTrack = { ...track }; + delete nextTrack.isMain; + return nextTrack; +} diff --git a/apps/web/src/services/storage/migrations/v23-to-v24.ts b/apps/web/src/services/storage/migrations/v23-to-v24.ts new file mode 100644 index 00000000..fe952bb1 --- /dev/null +++ b/apps/web/src/services/storage/migrations/v23-to-v24.ts @@ -0,0 +1,16 @@ +import { StorageMigration } from "./base"; +import type { ProjectRecord } from "./transformers/types"; +import { transformProjectV23ToV24 } from "./transformers/v23-to-v24"; + +export class V23toV24Migration extends StorageMigration { + from = 23; + to = 24; + + async transform(project: ProjectRecord): Promise<{ + project: ProjectRecord; + skipped: boolean; + reason?: string; + }> { + return transformProjectV23ToV24({ project }); + } +} diff --git a/apps/web/src/services/storage/service.ts b/apps/web/src/services/storage/service.ts index 3a014894..1aea0297 100644 --- a/apps/web/src/services/storage/service.ts +++ b/apps/web/src/services/storage/service.ts @@ -21,7 +21,7 @@ import { migrations, runStorageMigrations, } from "@/services/storage/migrations"; -import type { Bookmark, TimelineTrack, TScene } from "@/lib/timeline"; +import type { Bookmark, SceneTracks, TScene } from "@/lib/timeline"; function normalizeBookmarks({ raw }: { raw: unknown }): Bookmark[] { if (!Array.isArray(raw)) return []; @@ -116,18 +116,18 @@ class StorageService { private stripAudioBuffers({ tracks, }: { - tracks: TimelineTrack[]; - }): TimelineTrack[] { - return tracks.map((track) => { - if (track.type !== "audio") return track; - return { + tracks: SceneTracks; + }): SceneTracks { + return { + ...tracks, + audio: tracks.audio.map((track) => ({ ...track, elements: track.elements.map((element) => { const { buffer: _buffer, ...rest } = element; return rest; }), - }; - }); + })), + }; } async saveProject({ project }: { project: TProject }): Promise<void> { @@ -178,11 +178,7 @@ class StorageService { id: scene.id, name: scene.name, isMain: scene.isMain, - tracks: (scene.tracks ?? []).map((track) => - track.type === "video" - ? { ...track, isMain: track.isMain ?? false } // legacy: isMain was optional - : track, - ), + tracks: scene.tracks, bookmarks: normalizeBookmarks({ raw: scene.bookmarks }), createdAt: new Date(scene.createdAt), updatedAt: new Date(scene.updatedAt), |
