@@ -2,6 +2,10 @@ import { existsSync, promises as fs } from "node:fs";
22import { dirname } from "node:path" ;
33import type { FlaggedAccountStorageV1 } from "../storage.js" ;
44
5+ function getFlaggedBackupPaths ( path : string ) : string [ ] {
6+ return [ `${ path } .bak` , `${ path } .bak.1` , `${ path } .bak.2` ] ;
7+ }
8+
59export async function loadFlaggedAccountsState ( params : {
610 path : string ;
711 legacyPath : string ;
@@ -12,6 +16,34 @@ export async function loadFlaggedAccountsState(params: {
1216 logInfo : ( message : string , details : Record < string , unknown > ) => void ;
1317} ) : Promise < FlaggedAccountStorageV1 > {
1418 const empty : FlaggedAccountStorageV1 = { version : 1 , accounts : [ ] } ;
19+ if ( existsSync ( params . resetMarkerPath ) ) {
20+ return empty ;
21+ }
22+ const loadFlaggedBackup = async ( ) : Promise < FlaggedAccountStorageV1 | null > => {
23+ for ( const backupPath of getFlaggedBackupPaths ( params . path ) ) {
24+ if ( ! existsSync ( backupPath ) ) {
25+ continue ;
26+ }
27+ try {
28+ const backupContent = await fs . readFile ( backupPath , "utf-8" ) ;
29+ const backupData = JSON . parse ( backupContent ) as unknown ;
30+ const recovered = params . normalizeFlaggedStorage ( backupData ) ;
31+ params . logInfo ( "Recovered flagged account storage from backup" , {
32+ from : backupPath ,
33+ to : params . path ,
34+ accounts : recovered . accounts . length ,
35+ } ) ;
36+ return recovered ;
37+ } catch ( backupError ) {
38+ params . logError ( "Failed to recover flagged account storage from backup" , {
39+ from : backupPath ,
40+ to : params . path ,
41+ error : String ( backupError ) ,
42+ } ) ;
43+ }
44+ }
45+ return null ;
46+ } ;
1547
1648 try {
1749 const content = await fs . readFile ( params . path , "utf-8" ) ;
@@ -28,10 +60,15 @@ export async function loadFlaggedAccountsState(params: {
2860 path : params . path ,
2961 error : String ( error ) ,
3062 } ) ;
31- return empty ;
63+ return ( await loadFlaggedBackup ( ) ) ?? empty ;
3264 }
3365 }
3466
67+ const recoveredBackup = await loadFlaggedBackup ( ) ;
68+ if ( recoveredBackup ) {
69+ return recoveredBackup ;
70+ }
71+
3572 if ( ! existsSync ( params . legacyPath ) ) {
3673 return empty ;
3774 }
@@ -129,6 +166,7 @@ export async function clearFlaggedAccountsOnDisk(params: {
129166 backupPaths : string [ ] ;
130167 logError : ( message : string , details : Record < string , unknown > ) => void ;
131168} ) : Promise < void > {
169+ let keepResetMarker = false ;
132170 try {
133171 await fs . writeFile ( params . markerPath , "reset" , {
134172 encoding : "utf-8" ,
@@ -145,7 +183,6 @@ export async function clearFlaggedAccountsOnDisk(params: {
145183 for ( const candidate of [
146184 params . path ,
147185 ...params . backupPaths ,
148- params . markerPath ,
149186 ] ) {
150187 try {
151188 await fs . unlink ( candidate ) ;
@@ -159,6 +196,21 @@ export async function clearFlaggedAccountsOnDisk(params: {
159196 if ( candidate === params . path ) {
160197 throw error ;
161198 }
199+ keepResetMarker = true ;
200+ }
201+ }
202+ }
203+ if ( ! keepResetMarker ) {
204+ try {
205+ await fs . unlink ( params . markerPath ) ;
206+ } catch ( error ) {
207+ const code = ( error as NodeJS . ErrnoException ) . code ;
208+ if ( code !== "ENOENT" ) {
209+ params . logError ( "Failed to clear flagged account storage" , {
210+ path : params . markerPath ,
211+ error : String ( error ) ,
212+ } ) ;
213+ throw error ;
162214 }
163215 }
164216 }
0 commit comments