import { Injectable, Logger } from '@nestjs/common'; import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; type RuntimeSettings = { /** When false, SuperAdmin stops SMS alerts to managers */ adminSmsEnabled: boolean; }; const DEFAULTS: RuntimeSettings = { adminSmsEnabled: true, }; @Injectable() export class RuntimeSettingsService { private readonly logger = new Logger(RuntimeSettingsService.name); private readonly filePath = join(process.cwd(), 'data', 'runtime-settings.json'); private cache: RuntimeSettings | null = null; getAdminSmsEnabled(): boolean { return this.read().adminSmsEnabled !== false; } setAdminSmsEnabled(enabled: boolean) { const next = { ...this.read(), adminSmsEnabled: Boolean(enabled) }; this.write(next); this.logger.log(`Admin SMS alerts ${next.adminSmsEnabled ? 'enabled' : 'disabled'}`); return next; } getPublic() { return { adminSmsEnabled: this.getAdminSmsEnabled(), }; } private read(): RuntimeSettings { if (this.cache) return this.cache; try { if (!existsSync(this.filePath)) { this.cache = { ...DEFAULTS }; return this.cache; } const raw = JSON.parse(readFileSync(this.filePath, 'utf8')) as Partial; this.cache = { adminSmsEnabled: raw.adminSmsEnabled !== false, }; return this.cache; } catch (error: any) { this.logger.warn(`Failed to read runtime settings: ${error?.message || error}`); this.cache = { ...DEFAULTS }; return this.cache; } } private write(settings: RuntimeSettings) { const dir = join(process.cwd(), 'data'); if (!existsSync(dir)) mkdirSync(dir, { recursive: true }); writeFileSync(this.filePath, JSON.stringify(settings, null, 2), 'utf8'); this.cache = settings; } }