()
| 81 | * Returns a mutable copy — call `writeConfig()` to persist changes. |
| 82 | */ |
| 83 | export function readConfig(): HyperframesConfig { |
| 84 | if (cachedConfig) return { ...cachedConfig }; |
| 85 | |
| 86 | if (!existsSync(CONFIG_FILE)) { |
| 87 | const config = { ...DEFAULT_CONFIG, anonymousId: randomUUID() }; |
| 88 | writeConfig(config); |
| 89 | return config; |
| 90 | } |
| 91 | |
| 92 | try { |
| 93 | const raw = readFileSync(CONFIG_FILE, "utf-8"); |
| 94 | const parsed = JSON.parse(raw) as Partial<HyperframesConfig>; |
| 95 | |
| 96 | const config: HyperframesConfig = { |
| 97 | telemetryEnabled: parsed.telemetryEnabled ?? DEFAULT_CONFIG.telemetryEnabled, |
| 98 | anonymousId: parsed.anonymousId || randomUUID(), |
| 99 | telemetryNoticeShown: parsed.telemetryNoticeShown ?? DEFAULT_CONFIG.telemetryNoticeShown, |
| 100 | commandCount: parsed.commandCount ?? DEFAULT_CONFIG.commandCount, |
| 101 | renderSuccessCount: parsed.renderSuccessCount ?? DEFAULT_CONFIG.renderSuccessCount, |
| 102 | lastFeedbackPromptAt: parsed.lastFeedbackPromptAt ?? DEFAULT_CONFIG.lastFeedbackPromptAt, |
| 103 | lastUpdateCheck: parsed.lastUpdateCheck, |
| 104 | latestVersion: parsed.latestVersion, |
| 105 | pendingUpdate: parsed.pendingUpdate, |
| 106 | completedUpdate: parsed.completedUpdate, |
| 107 | lastSkillsCheck: parsed.lastSkillsCheck, |
| 108 | skillsUpdateAvailable: parsed.skillsUpdateAvailable, |
| 109 | skillsOutdatedCount: parsed.skillsOutdatedCount, |
| 110 | skillsMissingCount: parsed.skillsMissingCount, |
| 111 | }; |
| 112 | |
| 113 | cachedConfig = config; |
| 114 | return { ...config }; |
| 115 | } catch { |
| 116 | // Corrupted config — reset |
| 117 | const config = { ...DEFAULT_CONFIG, anonymousId: randomUUID() }; |
| 118 | writeConfig(config); |
| 119 | return config; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | /** |
| 124 | * Persist config to disk. Updates the in-memory cache. |
no test coverage detected