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