| 46 | } |
| 47 | |
| 48 | export class FilePersistence implements Persistence { |
| 49 | #dataFolder: string; |
| 50 | |
| 51 | constructor(dataFolderOverride?: string) { |
| 52 | this.#dataFolder = dataFolderOverride ?? getDataFolder(); |
| 53 | } |
| 54 | |
| 55 | async loadState(): Promise<LocalState> { |
| 56 | const filePath = path.join(this.#dataFolder, STATE_FILE_NAME); |
| 57 | try { |
| 58 | await fs.access(filePath); |
| 59 | } catch { |
| 60 | // File doesn't exist. Not an error because new users do not have the state file. |
| 61 | return { |
| 62 | lastActive: '', |
| 63 | }; |
| 64 | } |
| 65 | |
| 66 | try { |
| 67 | const content = await fs.readFile(filePath, 'utf-8'); |
| 68 | return JSON.parse(content) as LocalState; |
| 69 | } catch (error) { |
| 70 | logger?.(`Failed to read telemetry state from ${filePath}:`, error); |
| 71 | void ClearcutLogger.get()?.logServerError({ |
| 72 | errorCode: ErrorCode.ERROR_CODE_PERSISTENCE_FILE_READ_FAILED, |
| 73 | }); |
| 74 | return { |
| 75 | lastActive: '', |
| 76 | }; |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | async saveState(state: LocalState): Promise<void> { |
| 81 | const filePath = path.join(this.#dataFolder, STATE_FILE_NAME); |
| 82 | try { |
| 83 | await fs.mkdir(this.#dataFolder, {recursive: true}); |
| 84 | await fs.writeFile(filePath, JSON.stringify(state, null, 2), 'utf-8'); |
| 85 | } catch (error) { |
| 86 | // Ignore errors during state saving to avoid crashing the server |
| 87 | logger?.(`Failed to save telemetry state to ${filePath}:`, error); |
| 88 | void ClearcutLogger.get()?.logServerError({ |
| 89 | errorCode: ErrorCode.ERROR_CODE_PERSISTENCE_FILE_SAVE_FAILED, |
| 90 | }); |
| 91 | } |
| 92 | } |
| 93 | } |
nothing calls this directly
no outgoing calls
no test coverage detected