import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { join } from 'node:path' import { app, safeStorage } from 'electron/main' export interface DesktopLoginCredentials { identifier: string password: string } interface PersistedLoginCredentials { version?: number identifier?: unknown encryptedPassword?: unknown } function credentialsPath(): string { return join(app.getPath('userData'), 'login-credentials.json') } function normalizeCredentials(input: unknown): PersistedLoginCredentials { if (!input || typeof input !== 'object') { return {} } return input as PersistedLoginCredentials } export function getSavedLoginCredentials(): DesktopLoginCredentials | null { try { if (!existsSync(credentialsPath())) { return null } const persisted = normalizeCredentials(JSON.parse(readFileSync(credentialsPath(), 'utf8'))) const identifier = typeof persisted.identifier === 'string' ? persisted.identifier : '' const encryptedPassword = typeof persisted.encryptedPassword === 'string' ? persisted.encryptedPassword : '' if (!identifier || !encryptedPassword || !safeStorage.isEncryptionAvailable()) { return null } const password = safeStorage.decryptString(Buffer.from(encryptedPassword, 'base64')) return password ? { identifier, password } : null } catch (error) { console.warn('[login-credentials] read failed', { message: error instanceof Error ? error.message : String(error), }) return null } } export function saveLoginCredentials(credentials: DesktopLoginCredentials): DesktopLoginCredentials { const identifier = credentials.identifier.trim() if (!identifier || !credentials.password) { clearSavedLoginCredentials() return { identifier: '', password: '' } } if (!safeStorage.isEncryptionAvailable()) { throw new Error('login_credentials_encryption_unavailable') } const encryptedPassword = safeStorage.encryptString(credentials.password).toString('base64') writeFileSync( credentialsPath(), JSON.stringify({ version: 1, identifier, encryptedPassword, updatedAt: new Date().toISOString(), }), 'utf8', ) return { identifier, password: credentials.password } } export function clearSavedLoginCredentials(): null { try { rmSync(credentialsPath(), { force: true }) } catch (error) { console.warn('[login-credentials] clear failed', { message: error instanceof Error ? error.message : String(error), }) } return null }