()
| 73 | } |
| 74 | |
| 75 | private async _readLogFile(): Promise<LogEntry[]> { |
| 76 | if (!this.logFilePath) { |
| 77 | throw new Error('Log file path not set during read attempt.'); |
| 78 | } |
| 79 | try { |
| 80 | const fileContent = await fs.readFile(this.logFilePath, 'utf-8'); |
| 81 | const parsedLogs = JSON.parse(fileContent); |
| 82 | if (!Array.isArray(parsedLogs)) { |
| 83 | console.debug( |
| 84 | `Log file at ${this.logFilePath} is not a valid JSON array. Starting with empty logs.`, |
| 85 | ); |
| 86 | await this._backupCorruptedLogFile('malformed_array'); |
| 87 | return []; |
| 88 | } |
| 89 | return parsedLogs.filter( |
| 90 | (entry) => |
| 91 | typeof entry.sessionId === 'string' && |
| 92 | typeof entry.messageId === 'number' && |
| 93 | typeof entry.timestamp === 'string' && |
| 94 | typeof entry.type === 'string' && |
| 95 | typeof entry.message === 'string', |
| 96 | ) as LogEntry[]; |
| 97 | } catch (error) { |
| 98 | const nodeError = error as NodeJS.ErrnoException; |
| 99 | if (nodeError.code === 'ENOENT') { |
| 100 | return []; |
| 101 | } |
| 102 | if (error instanceof SyntaxError) { |
| 103 | console.debug( |
| 104 | `Invalid JSON in log file ${this.logFilePath}. Backing up and starting fresh.`, |
| 105 | error, |
| 106 | ); |
| 107 | await this._backupCorruptedLogFile('invalid_json'); |
| 108 | return []; |
| 109 | } |
| 110 | console.debug( |
| 111 | `Failed to read or parse log file ${this.logFilePath}:`, |
| 112 | error, |
| 113 | ); |
| 114 | throw error; |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | private async _backupCorruptedLogFile(reason: string): Promise<void> { |
| 119 | if (!this.logFilePath) return; |
no test coverage detected