this repo has no description
1import type { MigrationDirection, MigrationState, StoredMigrationState } from "./types";
2
3const STORAGE_KEY = "tranquil_migration_state";
4const MAX_AGE_MS = 24 * 60 * 60 * 1000;
5
6export function saveMigrationState(state: MigrationState): void {
7 const storedState: StoredMigrationState = {
8 version: 1,
9 direction: state.direction,
10 step: state.direction === "inbound" ? state.step : state.step,
11 startedAt: new Date().toISOString(),
12 sourcePdsUrl: state.direction === "inbound" ? state.sourcePdsUrl : window.location.origin,
13 targetPdsUrl: state.direction === "inbound" ? window.location.origin : state.targetPdsUrl,
14 sourceDid: state.direction === "inbound" ? state.sourceDid : "",
15 sourceHandle: state.direction === "inbound" ? state.sourceHandle : "",
16 targetHandle: state.targetHandle,
17 targetEmail: state.targetEmail,
18 progress: {
19 repoExported: state.progress.repoExported,
20 repoImported: state.progress.repoImported,
21 blobsTotal: state.progress.blobsTotal,
22 blobsMigrated: state.progress.blobsMigrated,
23 prefsMigrated: state.progress.prefsMigrated,
24 plcSigned: state.progress.plcSigned,
25 },
26 lastError: state.error ?? undefined,
27 lastErrorStep: state.error ? state.step : undefined,
28 };
29
30 try {
31 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(storedState));
32 } catch {
33 }
34}
35
36export function loadMigrationState(): StoredMigrationState | null {
37 try {
38 const stored = sessionStorage.getItem(STORAGE_KEY);
39 if (!stored) return null;
40
41 const state = JSON.parse(stored) as StoredMigrationState;
42
43 if (state.version !== 1) return null;
44
45 const startedAt = new Date(state.startedAt).getTime();
46 if (Date.now() - startedAt > MAX_AGE_MS) {
47 clearMigrationState();
48 return null;
49 }
50
51 return state;
52 } catch {
53 return null;
54 }
55}
56
57export function clearMigrationState(): void {
58 try {
59 sessionStorage.removeItem(STORAGE_KEY);
60 } catch {
61 }
62}
63
64export function hasPendingMigration(): boolean {
65 return loadMigrationState() !== null;
66}
67
68export function getResumeInfo(): {
69 direction: MigrationDirection;
70 sourceHandle: string;
71 targetHandle: string;
72 sourcePdsUrl: string;
73 targetPdsUrl: string;
74 progressSummary: string;
75 step: string;
76} | null {
77 const state = loadMigrationState();
78 if (!state) return null;
79
80 const progressParts: string[] = [];
81 if (state.progress.repoExported) progressParts.push("repo exported");
82 if (state.progress.repoImported) progressParts.push("repo imported");
83 if (state.progress.blobsMigrated > 0) {
84 progressParts.push(
85 `${state.progress.blobsMigrated}/${state.progress.blobsTotal} blobs`,
86 );
87 }
88 if (state.progress.prefsMigrated) progressParts.push("preferences migrated");
89 if (state.progress.plcSigned) progressParts.push("PLC signed");
90
91 return {
92 direction: state.direction,
93 sourceHandle: state.sourceHandle,
94 targetHandle: state.targetHandle,
95 sourcePdsUrl: state.sourcePdsUrl,
96 targetPdsUrl: state.targetPdsUrl,
97 progressSummary: progressParts.length > 0
98 ? progressParts.join(", ")
99 : "just started",
100 step: state.step,
101 };
102}
103
104export function updateProgress(
105 updates: Partial<StoredMigrationState["progress"]>,
106): void {
107 const state = loadMigrationState();
108 if (!state) return;
109
110 state.progress = { ...state.progress, ...updates };
111 try {
112 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
113 } catch {
114 }
115}
116
117export function updateStep(step: string): void {
118 const state = loadMigrationState();
119 if (!state) return;
120
121 state.step = step;
122 try {
123 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
124 } catch {
125 }
126}
127
128export function setError(error: string, step: string): void {
129 const state = loadMigrationState();
130 if (!state) return;
131
132 state.lastError = error;
133 state.lastErrorStep = step;
134 try {
135 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
136 } catch {
137 }
138}